서브쿼리
'com.querydsl.jpa.JPAExpressions'사용
바로 코드를 보며 알아보자.
그전에 아래 테스트 코드들의 모든 각 테스트에 @BeforeEach가 적용된다.
@BeforeEach
public void before(){
queryFactory = new JPAQueryFactory(em);
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 10, teamB);
Member member4 = new Member("member4", 20, teamB);
Member member5 = new Member("member5", 55, teamB);
em.persist(member5);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
}
1. 나이가 가장 많은 회원 조회하기
/*나이가 가장 많은 회원 조회*/
@Test
void subQuery(){
// 서브쿼리에서 사용할 QMember를 하나 더 만들어줘야 한다.
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory.selectFrom(member)
.where(member.age.eq(
//서브쿼리
JPAExpressions.select(memberSub.age.max()).from(memberSub)
))
.fetch();
for (Member member : result) System.out.println("member = " + member);
}
출력결과:
member = Member(id=3, username=member5, age=55)
2. 나이가 평균 이상인 회원 조회하기
/*나이가 평균 이상인 회원 조회*/
@Test
void subQueryGoe(){
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory.selectFrom(member)
.where(member.age.goe(
JPAExpressions.select(memberSub.age.avg()).from(memberSub)
))
.fetch();
for (Member member : result) System.out.println("member = " + member);
}
출력결과:
member = Member(id=3, username=member5, age=55)
3. in절에 서브쿼리를 사용하여 나이가 10 이상인 회원들 조회하기
/* in subquery */
@Test
void subQueryIn(){
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();
for (Member member : result) System.out.println("member = " + member);
}
출력결과:
member = Member(id=3, username=member5, age=55)
member = Member(id=5, username=member2, age=20)
member = Member(id=7, username=member4, age=20)
4. select안에 서브쿼리 사용하기
void selectSubQuery(){
QMember memberSub = new QMember("memberSub");
List<Tuple> result = queryFactory.select(
member.username,
JPAExpressions.select(memberSub.age.avg()).from(memberSub)
).from(member).fetch();
for (Tuple tuple : result) System.out.println("tuple = " + tuple);
}
출력결과:
tuple = [member5, 23.0]
tuple = [member1, 23.0]
tuple = [member2, 23.0]
tuple = [member3, 23.0]
tuple = [member4, 23.0]
from 절의 서브쿼리 한계
JPA JPQL 서브쿼리의 한계점으로 from 절의 서브쿼리(인라인 뷰)는 지원하지 않는다. 당연히 Querydsl 도 지원하지 않는다. 하이버네이트 구현체를 사용하면 select 절의 서브쿼리는 지원한다. Querydsl도 하이버네이트 구현체를 사용하면 select 절의 서브쿼리를 지원한다.
from 절의 서브쿼리 해결방안
- 서브쿼리를 join으로 변경한다. (가능한 상황도 있고, 불가능한 상황도 있다.)
- 애플리케이션에서 쿼리를 2번 분리해서 실행한다.
- nativeSQL을 사용한다.
김영한님의 인프런 강의와 PDF를 바탕으로 정리하였습니다.
'JPA > Querydsl' 카테고리의 다른 글
Querydsl 07 - 프로젝션과 결과반환 (0) | 2022.01.19 |
---|---|
Querydsl 06 - Case문, 상수 문자 더하기 (0) | 2022.01.18 |
Querydsl 04 - 조인 (0) | 2022.01.17 |
Querydsl 03 - 기본문법(정렬, 페이징, 집합) (0) | 2022.01.17 |
Querydsl 02 - 기본문법(Q타입, 검색조건, 결과조회) (0) | 2022.01.16 |