728x90
배경
Querydsl을 작성하여 테스트하던 중 아래와 같은 에러를 만났다.
public Optional<Partner> searchPartnerByMerNo(String merNo) {
return Optional.ofNullable(
query.select(partner)
.from(merchant)
.innerJoin(merchant.partner, partner).fetchJoin()
.where(merchant.merchantNo.eq(merNo))
.fetchOne()
);
}
SemanticException: Query specified join fetching, but the owner of the fetched association was not present in the select List
해석해 보면 “조인된 연관관계의 주인이 select 절에 포함되지 않았다” 라고 한다.
개발 환경
- Java 17
- Spring Boot 3.4.x
- Spring Data JPA
- Querydsl
- Gradle
- IntelliJ
원인
원인은 fetchJoin에 있다. fetchJoin은 단순히 join해서 데이터를 가져오는 것뿐만이 아니라, 연관된 엔티티들을 한 번에 영속성 컨텍스트에 채워 넣겠다는 의미를 갖는다. (그러한 이유때문에 N+1을 해결하기 위한 방법으로 많이 사용된다.)
그런데 위 코드처럼 partner만 select하고 merchant는 select에서 빠져있으면, Hibernate는 어떤 엔티티를 기준으로 그래프를 로딩해야할지 알 수 없다. 여기서 owner 엔티티는 merchant이기 때문이다.
해결 방법
fetchJoin은 반드시 owner 엔티티를 select해야 한다. 이렇게 하면 merchant가 select 되고, partner도 fetchJoin을 통해 함께 로딩된다. 즉 한 번의 쿼리로 두 엔티티가 영속성 컨텍스트에 채워지게 된다.
query.select(merchant)
.from(merchant)
.join(merchant.partner, partner).fetchJoin()
.where(...);
만약 단순히 partner만 뽑아오고 싶다면, fetch Join은 사용하지 말아야한다.
query.select(partner)
.from(merchant)
.join(merchant.partner, partner)
.where(...)
728x90