[Spring] QueryDsl transform 및 SqmCaseSearched 오류 해결방법 with Hibernate 6.x

2023. 10. 5. 17:08·Java & Spring
목차
  1. 들어가기 전에
  2. 개요
  3. 원인
  4. 해결 방안
  5. 마무리
반응형

들어가기 전에

해당 포스팅은 아래 환경 기준으로 작성되었습니다.

JDK 17
Spring Boot 3.1.0
JPA + QueryDsl 5.0.0
Hibernate 6.2.2

 

개요

QueryDsl로 쿼리를 작성하던 중 transform을 사용하던 곳에서 아래와 같은 오류가 발생했다.

java.lang.Object org.hibernate.ScrollableResults.get(int)

쿼리를 작성하는 부분은 아무리 봐도 문제가 없고 이전 버전에서 잘 동작하던 쿼리이기도 했다.

코드를 들어가 보니 hibernate 6.x 버전으로 넘어오면서 ScrollableResults에서 get(int) 메소드가 사라져서 발생한 문제였다.

 

해당 이슈를 구글링해 보니 아래와 같은 해결책이 존재했다.

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

 

위 설정을 적용하니 transform 부분에서의 오류는 해결이 되었는데,

대신 CaseBuilder와 sum()을 같이 사용하는 쿼리에서 아래와 같은 오류가 발생했다.

org.hibernate.QueryException: Function argument [org.hibernate.query.sqm.tree.expression.SqmCaseSearched@8a53e5] of type [null] at specified position [1] in call arguments was not typed as an allowable function return type

해당 이슈는 구글링해도 비슷한 사례가 나오지 않았다.

위의 해결책을 적용하고 나서 발생한 오류이다 보니 간단하게는 각 쿼리에서 JPAQueryFactory를 다르게 적용해 주면 해결을 할 수 있겠지만,

쿼리마다 다르게 적용하는 부분이 번거롭기 때문에 두 이슈를 동시에 해결할 수 있는 방안을 강구하였고,

해결책을 찾게 되어 포스팅하게 되었다.

 

원인

기본적으로 Hibernate 5 버전 이상에서는 QueryDsl 템플릿으로 Hibernate5Templates를 사용한다.

JPAProvider 코드의 일부분. hibernate 5버전 이상에서는 Hibernate5Templates를 사용하는 것을 확인할 수 있다.

 

Hibernate5Templates은 HQLTemplates을 상속받은 클래스인데,

이 HQLTemplates에서 QueryHandler로 HibernateHandler를 사용한다.

HQLTemplates 코드의 일부분. HQLTemplates은 HibernateHandler를 QueryHandler로 사용하는 것을 확인할 수 있다.

 

transform에서의 이슈가 이 HibernateHandler를 통해 발생한다.

또한 기본적인 JPQLTemplates은 QueryHandler로 DefaultQueryHandler를 사용하므로 위의 해결책에서 기술했듯 JPAQueryFactory에서 JPQLTemplates.DEFAULT를 적용하여 QueryHandler를 DefaultQueryHandler로 바꿔주어 해결한다.

JPQLTemplates 코드의 일부분. JPQLTemplates.DEFAULT는 DefaultQueryHandler.DEFAULT를 사용한다.

 

하지만 위의 방식은 QueryHandler만 바꾸는 것이 아닌 템플릿 자체를 바꾸는 것인데,

템플릿을 JPQLTemplates로 바꾸니 CaseBuilder + sum() 등에서 오류가 발생하는 것으로 보아 JPQLTemplates은 Hibernate 관련하여 제대로 대응을 하지 못하는 것으로 추측할 수 있겠다.

 

해결 방안

해결 방안은 의외로 간단하다. Hibernate5Templates를 그대로 사용하면서 QueryHandler만 DefaultQueryHandler로 바꿔주면 되겠다.

다만 JPAQueryFactory에서 QueryHandler만 바꿔줄 수는 없으므로 Hibernate5Templates를 확장한 커스텀 클래스를 생성하여 적용해야 한다.

public class CustomHibernate5Templates extends Hibernate5Templates {
    @Override
    public QueryHandler getQueryHandler() {
        return DefaultQueryHandler.DEFAULT;
    }
}

JPQLTemplates에서는 getQueryHandler() 메소드를 통해 QueryHandler를 불러와서 사용하므로 해당 메소드를 Override 하여 DefaultQueryHandler를 적용한다.

 

커스텀 클래스를 생성했다면 아래와 같이 JPAQueryFactory에 연결해 주자.

@Bean
public JPAQueryFactory jpaQueryFactory() {
    return new JPAQueryFactory(new CustomHibernate5Templates(), entityManager);
}

위와 같이 적용하고 나면 위 두 이슈 모두 해결된 것을 확인할 수 있다.

 

마무리

해결된 코드 자체는 간단하지만 이런 경우는 라이브러리 코드를 뜯어보고 커스텀해야 하는 작업이라 원인 파악 및 해결하기까지 시간이 오래 걸린다.

워낙 구조가 복잡해서 적용된 부분 및 원인에 대해서 일일이 기록하지는 않았지만 필자 또한 해당 이슈 해결을 위해 계속 디버깅해 보고 원인을 추측하는 데 적지 않은 시간 소요가 발생했다.

개발을 하다 보면 이런 경우가 종종 발생할 수 있는데 라이브러리 내부에 들어가서 코드를 읽으며 정확한 동작 원리를 이해하는 것이 중요하다는 것을 다시금 느낀다.

ScrollableResults에서 get(int) 메소드가 사라지지 않았다면 이런 일은 없지 않았을까..?

 

참고 링크

https://github.com/querydsl/querydsl/issues/3428
 

java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)' with Hibernate 6.1.5.Final · Issue #34

Observed vs. expected behavior Observed: Caused by: java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)' at deployment.acoset-server-ear.ear//com.querydsl.jpa.Sc...

github.com

반응형

'Java & Spring' 카테고리의 다른 글

Spring Boot 무료로 배포하기 (Koyeb, GitHub)  (0) 2024.03.21
[Spring] eventListener, transactionalEventListener 예외 및 트랜잭션 전파 총정리  (0) 2023.12.29
[JAVA] 내부 resource 파일 활용하기  (0) 2023.07.29
[JAVA] LocalDate로 한국식 월 주차 구하기  (6) 2023.07.27
[JAVA] Calendar로 한국식 월 주차 구하기  (0) 2023.07.24
  1. 들어가기 전에
  2. 개요
  3. 원인
  4. 해결 방안
  5. 마무리
'Java & Spring' 카테고리의 다른 글
  • Spring Boot 무료로 배포하기 (Koyeb, GitHub)
  • [Spring] eventListener, transactionalEventListener 예외 및 트랜잭션 전파 총정리
  • [JAVA] 내부 resource 파일 활용하기
  • [JAVA] LocalDate로 한국식 월 주차 구하기
hojun-dev
hojun-dev
개발과 함께하는 일상을 그리는 블로그입니다.
개발 일상개발과 함께하는 일상을 그리는 블로그입니다.
  • hojun-dev
    개발 일상
    hojun-dev
  • 전체
    오늘
    어제
    • 분류 전체보기 (69)
      • Java & Spring (15)
      • Kubernetes (17)
      • Javascript (2)
      • Linux (2)
      • Setting (16)
      • Work (4)
      • 일상 (10)
      • 항해플러스 (3)
  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
hojun-dev
[Spring] QueryDsl transform 및 SqmCaseSearched 오류 해결방법 with Hibernate 6.x
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.