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