Hello

[Querydsl] Subquery 및 Result handling 본문

java

[Querydsl] Subquery 및 Result handling

nari0_0 2024. 7. 31. 10:31
728x90

ORM을 사용하면서 Subquery를 사용할 일이 있을까 생각했는데 필요한 경우가 생겨 Subquery 적용했던 내용을 정리 하려고 합니다. Subquery가 필요했던 이유는 집합 값이 필요했기 때문입니다.

 

queryDsl에서 Subquery를 사용하는 방법은 간단합니다. JPAExpressions를 통해 결과 값 하나를 반환하는 쿼리를 작성합니다. 그리고 select 또는 where 중 필요한 구문에서 적용해 사용할 수 있습니다.

 

Select

JPQLQuery<Long> questMaxSubquery = JPAExpressions
        .select(qQuest.complete.max())
        .from(qQuest)
        .where(qQuest.id.eq(qUserQUest.quest.id));

QueryResults<UserQuest> results = jpaQueryFactory.select(
                Projections.constructor(UserQuest.class,
                        qUserQuest.id,
                        questMaxSubquery
                )).from(qUserQuest)
        ...join, where, orderby, limit 등..
        .fetchResults();
        
--결과 쿼리
select
        userQUest0_.no as col_0_0_,
        (select
            max(quest1.complete) 
        from
            casino_x_configdb.TB_Quest quest1_ 
        where
            quest6_.questId=userQuest0_.questId) as col_10_0_
    from
        casino_x_userdb.TB_UserQuest userQuest0_

Where

LocalDateTime localDateTime = LocalDateTime.now().minusDays(7)
JPQLQuery<Long> questWhereSubquery = JPAExpressions
        .select(qQuestUser.questId)
        .from(qQuestUser)
        .where(qQuestUser.date.gt(localDateTime));

QueryResults<UserQuest> results = jpaQueryFactory.select(
                Projections.constructor(UserQuest.class,
                        qUserQuest.id,
                        ...
                )).from(qQuest)
                .where(qQuest.id.in(questWhereSubquery))
        ...join, where, orderby, limit 등..
        .fetchResults();

+결과 처리

Projections.constructor 사용 시 생성자에서 받는 매개변수 순서대로 값을 넣어준다.

QueryResults<UserQuest> results = jpaQueryFactory.select(
                Projections.constructor(UserQuest.class,
                        qUserQuest.id,
                        qQuest.id.as("questId"),
                        ...
                        questMaxSubquery
                )).from(qUserQuest)
        ...join, where, orderby, limit 등..
        .fetchResults();

Projections.field 또는 Projections.bean 사용 시 field명과 동일한지 확인한다.

예를들어 qUserQuest.id와 qQuest.id 값을 결과에 받아야 할 경우 as 를 통해 명시적으로 field명과 맞춰서 사용해야한다.

Subquery는 ExpressionUtiles.as를 사용하면 된다.

QueryResults<UserQuest> results = jpaQueryFactory.select(
                Projections.bean(UserQuest.class,
                        qUserQuest.id,
                        ...
                        ExpressionUtils.as(questMaxSubquery, "questMax")
                )).from(qUserQuest)
        ...join, where, orderby, limit 등..
        .fetchResults();

 

참고 : https://jojoldu.tistory.com/379

http://querydsl.com/static/querydsl/latest/reference/html_single/#result_handling

http://querydsl.com/static/querydsl/5.0.0/reference/html_single/#d0e425

 

728x90