JAVA/JPA & Querydsl

SpringBoot3.x 버전에서 QueryDsl 사용 설정 시 이슈 정리

laughcryrepeat 2023. 7. 17. 17:40

 

1. 쿼리 결과 집합 transform, ResultTransformer and GroupBy 사용하기

QueryDsl 사용시 쿼리 결과를 다양한 타입으로 결과 집합, 그룹화하여 받을 수 있는 transform + GroupBy를 유용하게 사용했었습니다. SpringBoot 3.x 버전 이상의 환경에서는 2.x 버전과 다른 설정을 해주어야 사용이 가능합니다.

 

JPAQueryFactory에 JPQLTemplates.DEFAULT 설정을 적용해 주어야만 사용이 가능합니다.

@Configuration
public class QuerydslConfig {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory(){
        return new JPAQueryFactory(JPQLTemplates.DEFAULT, entityManager);
    }
}

 

그렇지 않으면 다음과 같은 에러가 나면서 정상 작동하지 않습니다.

Caused by: java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)'

 

2. CaseBuilder 사용

JPAQueryFactory에 JPQLTemplates.DEFAULT 설정을 적용한 후, 잘되던 CaseBuilder가 동작하지 않았습니다.

기존 쿼리는 다음과 같았습니다.

 

List<TestResponse> content
                = queryFactory.select(
                        Projections.fields(TestResponse.class,
                                test.id,
                                new CaseBuilder()
                                        .when((testSetting.startsAt.gt(now)))
                                        .then("waiting")
                                        .when((testSetting.endsAt.lt(now)))
                                        .then("closed")
                                        .when((testSetting.startsAt.loe(now).and(testSetting.endsAt.goe(now))))
                                        .then("progress")
                                        .otherwise("none")
                                        .max().as("progressStatus"),
                                new CaseBuilder()
                                        .when((candidateSession.finishedAt.isNotNull()))
                                        .then(1L)
                                        .otherwise(0)
                                        .sum().as("completeCandidateCount"),
                                candidateSession.id.count().coalesce(0L).as("totalCandidateCount")
                        ))
                .from(test)
                .leftJoin(test.testSetting, testSetting)
                .leftJoin(test.candidateSessions, candidateSession)
                .where(whereClause(testType))
                .fetch();

 

첫번째 CaseBuilder는 정상 동작 하였으나 두번째 CaseBuilder에서 오류가 생겼다.

type [null] at specified position [1] in call arguments was not typed as an allowable function return type caseBuilder

JPQLTemplates.DEFAULT 설정한 후엔 숫자값만 넣어주면 안되고 명확한 Type Expression을 넣어주어야 했다.

그래서 다음과 같은 쿼리로 모두 수정한 후에는 정상 동작하였다.

 

List<TestResponse> content
                = queryFactory.select(
                        Projections.fields(TestResponse.class,
                                test.id,
                                new CaseBuilder()
                                        .when((testSetting.startsAt.gt(now)))
                                        .then("waiting")
                                        .when((testSetting.endsAt.lt(now)))
                                        .then("closed")
                                        .when((testSetting.startsAt.loe(now).and(testSetting.endsAt.goe(now))))
                                        .then("progress")
                                        .otherwise("none")
                                        .max().as("progressStatus"),
                                new CaseBuilder()
                                        .when((candidateSession.finishedAt.isNotNull()))
                                        .then(Expressions.asNumber(1).castToNum(Long.class))
                                        .otherwise(Expressions.asNumber(0L).castToNum(Long.class))
                                        .sum().as("completeCandidateCount"),
                                candidateSession.id.count().coalesce(0L).as("totalCandidateCount")
                        ))
                .from(test)
                .leftJoin(test.testSetting, testSetting)
                .leftJoin(test.candidateSessions, candidateSession)
                .where(whereClause(testType))
                .fetch();

 

 

Reference

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

 

Querydsl Reference Guide

The Java 6 APT annotation processing functionality is used in Querydsl for code generation in the JPA, JDO and Mongodb modules. This section describes various configuration options for the code generation and an alternative to APT usage. 3.3.1. Path initi

querydsl.com

https://github.com/querydsl/querydsl/blob/master/querydsl-core/src/test/java/com/querydsl/core/group/GroupByMapTest.java