Hibernate 6.x 에서 AliasCollisionException
kindof
·2026. 5. 14. 16:15
Hibernate 5.x를 쓰던 프로젝트에서 6.x를 쓰는 프로젝트로 이관하면서 몇 가지 문제를 만나고 있다.
그 중 하나인 QueryDSL Q 클래스 alias 문제에 대해 간략하게 정리한다.
https://docs.hibernate.org/orm/6.0/migration-guide/#query
6.0 Migration Guide
As back-ground, Hibernate does understand whether a fetch is actually, truly circular. It simply understands that while walking a fetch-graph it encounters the same table/column(s) making up a particular foreign-key. In this case, it simply stops walking t
docs.hibernate.org
Hibernate 6 부터는 HQL/Criteria 쿼리가 새 트리 모델(SQM)로 파싱된다고 한다.
기존에는 문자열 기반으로 비교적 느슨하게 해석하던 부분이 있었지만, Hibernate 6에서는 HQL을 먼저 SQM(Semantic Query Model) 트리로 변환한 뒤 이를 SQL AST로 변환해 dialect 별 SQL을 생성한다는 것이다.
이 과정에서 Hibernate 5.x를 포함한 이전 버전보다 쿼리에 대한 검증이 빡빡해졌고 5.x가 허용하던 모호한 쿼리들이 SQM 파싱 과정에서 예외를 던지게 된다.
한편, 아래 공식 스펙을 보면 JPA의 JPQL 규칙에서는 FROM 절에서 선언되는 identification variable(alias)을 두 번 선언할 수 없다고 이미 명시하고 있다.
https://jakarta.ee/specifications/persistence/3.1/jakarta-persistence-spec-3.1.html#a4765
Jakarta Persistence
The following are reserved identifiers: ABS, ALL, AND, ANY, AS, ASC, AVG, BETWEEN, BIT_LENGTH, BOTH, BY, CASE, CEILING, CHAR_LENGTH, CHARACTER_LENGTH, CLASS, COALESCE, CONCAT, COUNT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, DELETE, DESC, DISTINCT, EL
jakarta.ee
Hibernate 5.x는 이 규칙을 엄격히 검증하진 않아서 아래처럼 같은 alias를 가져도 통과할 수 있었다.
query.leftJoin(channel.master, QMember.member)
.leftJoin(channel.owner, QMember.member);
하지만 Hibernate 6.x 부터는 위 쿼리는 AliasCollisionException을 던진다. 두 join이 모두 같은 alias 를 쓰기 때문이다.
따라서 이를 회피하려면 alias 를 직접 지정해 인스턴스를 분리해줘야 한다.
QMember master = new QMember("masterMember");
QMember owner = new QMember("ownerMember");
query.leftJoin(channel.master, master)
.leftJoin(channel.owner, owner);
정리하자면
Hibernate 6.x에서 QueryDSL 쓸 때 정적 Q엔티티는 한 번만 쓰고, 그 뒤 동일 엔티티가 다시 필요할 때마다 new로 인스턴스를 새로 만들면 되겠다.
'Spring Framework' 카테고리의 다른 글
| Spring @Async를 쓰면서 생각해볼 것들 (0) | 2026.02.13 |
|---|---|
| 스프링 배치 SynchronizedItemStreamReader에 대해 (1) | 2026.01.17 |
| jackson-databind, AUTO_DETECT_IS_GETTERS 옵션(is getter) (1) | 2024.02.14 |
| Spring 5.2.X 버전에서 @RequestParam required = true 옵션은 null safety 하지 않다. (1) | 2024.01.28 |
| Spring RestTemplate 까보기 (1) | 2024.01.11 |