-
Querydsl - 서브 쿼리JPA/Querydsl 2023. 8. 13. 00:18
서브 쿼리는 com.querydsl.jpa.JPAExpressions을 사용한다.
/** * 나이가 가장 많은 회원 조회 */ @Test public void subQuery() { QMember memberSub = new QMember("memberSub"); List<Member> result = queryFactory .selectFrom(member) .where(member.age.eq( JPAExpressions .select(memberSub.age.max()) .from(memberSub) )) .fetch(); assertThat(result).extracting("age") .containsExactly(40); }
.where(member.age.eq(JPAExpressions.select(memberSub.age.max()).from(memberSub)))
서브 쿼리인 값이 40이 될 것이고 where문의 조건은 나이가 40인 사람이 될 것이다.
평균 이상을 조회
/** * 나이가 평균 나이 이상인 회원 */ @Test public void subQueryGoe() throws Exception { QMember memberSub = new QMember("memberSub"); List<Member> result = queryFactory .selectFrom(member) .where(member.age.goe( // goe의 뜻은 평균보다 큰 것을 찾는다는 뜻 JPAExpressions .select(memberSub.age.avg()) .from(memberSub) )) .fetch(); assertThat(result).extracting("age") .containsExactly(30, 40); }
평균보다 나이가 많은 사람을 조회하는 서브 쿼리이다. JPAExpression을 통해 나이 평균을 select했고, goe()를 통해 평균보다 나이가 많은 사람을 최종적으로 select한다.
in 절을 사용
/** * 서브쿼리 여러 건 처리, in 사용 */ @Test public void subQueryIn() throws Exception { QMember memberSub = new QMember("memberSub"); List<Member> result = queryFactory .selectFrom(member) .where(member.age.in( JPAExpressions .select(memberSub.age) .from(memberSub) .where(memberSub.age.gt(10)) )) .fetch(); assertThat(result).extracting("age") .containsExactly(20, 30, 40); }
in 절을 사용할 때에도 서브 쿼리는 똑같이 들어간다.
select 절에 서브 쿼리 사용
@Test public void selectSubQuery() { QMember memberSub = new QMember("memberSub"); List<Tuple> fetch = queryFactory .select(member.username, // JPAExpressions -> static import .select(memberSub.age.avg()) .from(memberSub) ).from(member) .fetch(); for (Tuple tuple : fetch) { System.out.println("username = " + tuple.get(member.username)); System.out.println("age = " + tuple.get(JPAExpressions.select(memberSub.age.avg()) .from(memberSub))); } }
select 절에 서브 쿼리를 사용하는 것도 크게 다르지 않다.
참고로 JPAExpressions는 static import로 생략을 해줄 수 있다.
JPA의 서브쿼리는 from 절에서 서브쿼리를 사용할 수 없다. Querydsl에서도 지원하지 않지만 하이버네이트 구현체를 사용하면 select 절에서는 서브쿼리를 사용할 수 있다.
from 절의 서브쿼리를 하려면?
1. 서브쿼리를 join으로 변경한다. (불가능할 때도 있음)
2. 애플리케이션에서 쿼리를 2번 분리해서 실행한다.
3. nativeSQL을 사용한다.
'JPA > Querydsl' 카테고리의 다른 글
Dto로 프로젝션 결과 반환 (0) 2023.08.13 Querydsl - Case 문 (0) 2023.08.13 Querydsl - 조인 (0) 2023.08.13 Querydsl - 정렬과 페이징, 집합 (0) 2023.08.12 Querydsl - 검색(select)과 결과 조회 (0) 2023.08.12