
이번 글에서는 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();
}
이번 글에 이어 다음 글에서도 기본 문법에 대해 알아보겠습니다.