[ 김영한 Querydsl #2 ] - 기본 문법 (1) : 조건, fetch, 정렬, 페이징, 집합, 상수, concat

정동욱·2023년 7월 15일
0
post-thumbnail

이번 글에서는 Querydsl을 이용해 쿼리짜는 방법에 대해 알아보겠습니다.

먼저 조회문에서 WHERE절에 조건을 2개 넣는 경우 아래와 같은 코드를 사용할 수 있습니다.

@Test
void search() {
	Member findMember = queryFactory
			.selectFrom(member)
			.where(member.username.eq("memberA")
					.and(member.age.eq(10)))
			.fetchOne();

	assertThat(findMember.getUsername()).isEqualTo("memberA");
}

보면 WHERE절에 AND를 붙여 조건이 2개가 되게끔 했는데요, 아래와 같은 방식도 가능합니다.

@Test
void searchAndParam() {
	Member findMember = queryFactory
			.selectFrom(member)
			.where(
					member.username.eq("memberA"),
					member.age.eq(10)
			)
			.fetchOne();
            
	assertThat(findMember.getUsername()).isEqualTo("memberA");
}

WHERE절 내부를 하나로 묶음으로써 보다 가독성 좋은 코드가 되었습니다. 이 방식은 가독성뿐만 아니라 조건 내부에 null이 들어가도 아무런 문제가 생기지 않아 동적 쿼리를 짜기 쉽게 해주는데요, 이후 강의에서 이 부분에 대해 알려준다고 합니다.

그리고 이번에는 쿼리를 작성 후 fetch 부분을 볼텐데요, 최종적으로 조회할 결과물을 정하는 역할입니다.

fetchOne(): 단건 조회 (2개 이상일 경우 NonUniqueResultException)
fetch(): List 조회
fetchFirst(): 단건이든 아니든 1개만 조회 (=limit(1).fetchOne())
fetchResult(): total, limit, offset 등 제공해 페이징에 용이 (Deprecated)
fetchCount(): count 수 조회 (Deprecated)


다음으로 정렬하는 방법에 대해 알아보겠습니다. 정렬도 매우 간단한데 코드로 보겠습니다.

@Test
void sort() {
	Member memberE = new Member(5L, null, 100);
	Member memberF = new Member(6L, "memberF", 100);
	Member memberG = new Member(7L, "memberG", 100);
        
    em.persist(memberE);
	em.persist(memberF);
	em.persist(memberG);

	// 1. 회원 나이 내림차순
	// 2. 회원 이름 올림차순
	// 3. 회원 이름이 없으면 마지막에 출력
	List<Member> members = queryFactory
			.selectFrom(member)
			.where(member.age.eq(100))
			.orderBy(member.age.desc(), member.username.asc().nullsLast())
			.fetch();

	Member memberF = members.get(0);
	Member memberG = members.get(1);
	Member memberNull = members.get(2);

	assertThat(memberF.getUsername()).isEqualTo("memberF");
	assertThat(memberG.getUsername()).isEqualTo("memberG");
	assertThat(memberNull.getUsername()).isNull();
}

그리고 페이징 처리하는 방법에 대해 알아보겠습니다. 위에서 본 fetchResult()를 사용할 수도 있고, 개별적으로 사용할 수도 있습니다.

@Test
void paging1() {
	List<Member> members = queryFactory
			.selectFrom(member)
			.orderBy(member.id.asc())
			.offset(0)
			.limit(2)
			.fetch();

	assertThat(members.size()).isEqualTo(2);
	assertThat(members.get(0).getUsername()).isEqualTo("memberA");
	assertThat(members.get(1).getUsername()).isEqualTo("memberB");
}

@Test
void paging2() {
	QueryResults<Member> memberQueryResults = queryFactory
			.selectFrom(member)
			.orderBy(member.id.asc())
			.offset(0)
			.limit(2)
			.fetchResults();

	assertThat(memberQueryResults.getTotal()).isEqualTo(7);
	assertThat(memberQueryResults.getOffset()).isEqualTo(0);
	assertThat(memberQueryResults.getLimit()).isEqualTo(2);
	assertThat(memberQueryResults.getResults().size()).isEqualTo(2);
	}

그리고 집합에 대해 알아보겠습니다. 이것도 마찬가지로 코드로 보겠습니다.

// 팀의 이름과 팀의 평균 연령 구하기
@Test
void group() {
	List<Tuple> tuples = queryFactory
			.select(team.name, member.age.avg())
			.from(member)
			.join(member.team, team)
			.groupBy(team.name)
			.fetch();
		
	Tuple teamA = tuples.get(0);
	Tuple teamB = tuples.get(1);
		
	assertThat(teamA.get(team.name)).isEqualTo("teamA");
	assertThat(teamA.get(member.age.avg())).isEqualTo(15);

	assertThat(teamB.get(team.name)).isEqualTo("teamB");
	assertThat(teamB.get(member.age.avg())).isEqualTo(35);
}

또 상수를 함께 조회하는 방법을 알아보겠습니다. Expressions 객체를 사용해 원하는 문자 등을 나타낼 수 있습니다.

@Test
void constant() {
	List<Tuple> result = queryFactory
			.select(member.username, Expressions.constant("남성"))
			.from(member)
			.fetch();
	}

마지막으로 concat을 이용해 조회할 결과물을 커스텀해보겠습니다.

@Test
void concat() {
	List<String> result = queryFactory
			.select(member.username.concat(" : ").concat(member.team.name))
			.from(member)
			.fetch();
}

이번 글에 이어 다음 글에서도 기본 문법에 대해 알아보겠습니다.

profile
거인의 어깨 위에서 탭댄스를

0개의 댓글