[QueryDSL] Subquery

KMS·2022년 5월 9일
0

QueryDSL

목록 보기
6/8

WHERE Subquery

	@Test
    void subQuery() {
        factory = new JPAQueryFactory(em);
        QMember member = QMember.member;
        QMember subMember = new QMember("sub"); // 서브쿼리 안에 있는 Member는 Alias 를 다르게 해줘야 하기 때문에 new QMember(name) 으로 Alias를 설정해서 생성

        List<Member> result = factory
                .selectFrom(member)
                .where(member.age.eq(
                        JPAExpressions
                                .select(subMember.age.max())
                                .from(subMember)
                ))
                .fetch();
        //eq 외 gt, goe 등등 모두 사용 가능

        Assertions.assertThat(result).extracting("age")
                .containsExactly(55);

    }
SELECT *FROM member WHERE age = (SELECT max(sub.age) FROM member sub);

WHERE Subquery + IN

	@Test
    void subQueryIn() {
        factory = new JPAQueryFactory(em);
        QMember member = QMember.member;
        QMember subMember = new QMember("sub"); // 서브쿼리 안에 있는 Member는 Alias 를 다르게 해줘야 하기 때문에 new QMember(name) 으로 Alias를 설정해서 생성

        List<Member> result = factory
                .selectFrom(member)
                .where(member.age.in(
                        JPAExpressions
                                .select(subMember.age)
                                .from(subMember)
                                .where(subMember.age.gt(40))
                ))
                .fetch();

        Assertions.assertThat(result).extracting("age")
                .containsExactly(45, 55);

    }
SELECT * FROM member WHERE age IN (SELECT sub.age FROM member sub WHERE sub.age > 40);

SELECT Subquery

	@Test
    void subQuerySelect() {
        factory = new JPAQueryFactory(em);
        QMember member = QMember.member;
        QMember subMember = new QMember("sub"); // 서브쿼리 안에 있는 Member는 Alias 를 다르게 해줘야 하기 때문에 new QMember(name) 으로 Alias를 설정해서 생성

        List<Tuple> result = factory.select(member.username,
                        JPAExpressions
                                .select(subMember.age.avg())
                                .from(subMember))
                .from(member)
                .fetch();

        for (Tuple tuple : result) {
            System.out.println("tuple = " + tuple);
        }


        Assertions.assertThat(result.get(0).get(1, Double.class)).isEqualTo(40);
    }
SELECT member.username, (SELECT avg(sub.age) FROM member sub) FROM member;

주의할 점:
1. 서브쿼리를 사용할때는 각각 다른 Alias로 해줘야 하는데, QueryDSL에서는 Q 엔티티를 생성할때 Alias를 지정해 줄 수 있습니다. 예를 들어, Member에 대해서 서브쿼리를 실행할 경우에는, new QMember("A")으로 SQL에서 'Member as A'/'Member A'와 같은 효과를 줄 수 있습니다.
2. JPA JPQL에서 기본적으로 from에서의 서브쿼리는 지원하지 않습니다. 그렇기 때문에 QueryDSL에서도 from에서 서브쿼리를 실행 할 수 없습니다.

profile
Student at Sejong University Department of Software

0개의 댓글