문제 정의

“Lazy Loading으로 설정된 다수의 하위 엔티티에 대해서, 엔티티 별로 각각의 쿼리를 추가로 요청하는 문제” (1 : 상위 엔티티에 대한 쿼리, N : 하위 엔티티에 대한 쿼리(하위 엔티티 개수 만큼))

해결 방법

*Academy ← 1:n → Subject ← 1:n → teacher

1. join fetch

쿼리문(상위 엔티티에 대한 쿼리)에 함께 가지고 오고 싶은 하위 엔티티를 정의해 준다.

@Query("select a from Academy a join fetch a.subjects")
List<Academy> findAllJoinFetch();

2. @EntityGraph

쿼리문을 변경하지 않고, 특정 하위 엔티티에 대해 Eager Loading을 지정하여 준다.

@EntityGraph(attributePaths = "subjects")
@Query("select a from Academy a")
List<Academy> findAllEntityGraph();

조회 Depth를 더 깊게 할 수도 있다.

@EntityGraph(attributePaths = {"subjects", "subjects.teacher"})
@Query("select a from Academy a")
List<Academy> findAllEntityGraphWithTeacher();

SideEffect

join fetch와 @EntityGraph의 차이점

join fetch는 inner join, @EntityGraph는 Outer join을 이용하여 쿼리를 생성, 조회한다.

카테시안 곱과 중복

join fetch와 @EntityGraph 모두 조인연산을 사용하기 때문에, “카테시안 곱”이 발생하여, 상위 엔티티의 불필요한 중복이 생길 수 있다.