트러블 슈팅 - QueryDSL, From Fetch 오류

Zyoon·2025년 6월 25일

트러블슈팅

목록 보기
8/11
post-thumbnail

❗Hibernate 6에서 발생한 from fetch 오류, QueryDSL로 해결


기존 코드

QTodo todo = QTodo.todo;
QUser user = QUser.user;

return Optional.ofNullable(
    queryFactory
        .select(todo)
        .leftJoin(todo.user, user).fetchJoin()
        .where(todo.id.eq(todoId))
        .fetchOne()
);

QueryDSL을 사용해 Todo 엔티티를 User와 fetch join으로 조회하려고 했다.

Hibernate 6 환경에서 위 코드는 실행 시 JPQL 문법 오류를 발생시켰다.


문제점

fetchJoin()을 사용하는 위 코드에서 다음과 같은 JPQL을 생성했다:

select todo
from fetch todo.user as user
where todo.id = ?1

하지만 from fetchJPQL 문법상 허용되지 않는 구문이다.

Hibernate 6의 JPQL 파서는 더 엄격해졌기 때문에, 이렇게 잘못된 구문은 SyntaxException을 유발한다.

Caused by: java.lang.IllegalArgumentException: org.hibernate.query.SyntaxException: At 2:15 and token '.', mismatched input '.', expecting one of the following tokens: <EOF>, ',', CROSS, FULL, GROUP, INNER, JOIN, LEFT, ORDER, OUTER, RIGHT, WHERE [select todo
from fetch todo.user as user
where todo.id = ?1]

해결 방법

  • .select(todo).selectFrom(todo)로 변경했다.
  • selectFrom(todo)는 내부적으로 select(todo).from(todo)를 포함하며,
  • JPQL의 from 절을 명시적으로 생성from fetch와 같은 오류를 방지할 수 있다.
return Optional.ofNullable(
    queryFactory
        .selectFrom(todo)
        .leftJoin(todo.user, user).fetchJoin()
        .where(todo.id.eq(todoId))
        .fetchOne()
);

결과

  • Hibernate가 생성하는 JPQL 문법 오류(from fetch ...) 문제 해결
  • JPQL 파싱 예외 (SyntaxException) 완전 제거
  • QueryDSL 쿼리의 명시성 향상 및 Hibernate 6 호환성 확보
  • fetch join을 사용하는 쿼리에서 불안정한 동작 제거 및 예측 가능성 향상

참고 사항

  • Hibernate 6부터는 JPQL 파싱이 더 엄격해졌으므로 QueryDSL 쿼리 작성 시 .selectFrom(...) 사용을 권장
  • querydsl-jpa5.0.0-jakarta 이상 버전 사용 시 Hibernate 6과 호환 가능
profile
기어 올라가는 백엔드 개발

0개의 댓글