문제 상황


OneToMany 관계의 엔티티들이 있습니다.

그리고 이 엔팉티의 자식들을 모두 가져와야 하는 서비스 메소드가 있습니다.

이때 조회된 부모의 수만큼 자식 테이블의 쿼리가 추가 발생하는 JPA N+1 문제가 발생합니다. 이를 해결하기 위해서 Fetch Join을 적용하였습니다.

@Query("SELECT p FROM Profile p " +
        "INNER JOIN FETCH p.user " +
        "LEFT JOIN FETCH p.preferStyles " +
         "LEFT JOIN FETCH p.preferLocations " +
         "LEFT JOIN FETCH p.preferPrices " +
         "LEFT JOIN FETCH p.awards " +
         "LEFT JOIN FETCH p.workExperiences " +
         "WHERE p.isDeleted = false")
    Page<Profile> findAllByIsDeletedFalse(Pageable pageable);

이때 1:N 관계의 자식 테이블 여러곳에 Fetch Join을 사용하면 아래와 같은 에러가 발생합니다.

cannot simultaneously fetch multiple bags: 
[com.tk.gg.users.domain.model.Profile.awards, com.tk.gg.users.domain.model.Profile.preferLocations]

문제 원인


⇒ JPA에서 Fetch Join 조건으로 XToOne으로 연관되어 있는 엔티티는 몇 개든 조회가능하지만, XToMany로 연관되어 있는 엔티티는 1개만 가능하다. 따라서 OneToMany로 5개를 Fetch Join을 통해서 가져오려고 하니 MultipleBagFetchException 에러가 발생한 것이다.

해결 방법


  1. Hibernate default_batch_fetch_size를 조절하면, Fetch Join 보다는 성능이 조금 떨어지지만, N+1 문제가 발생하지 않으며 최소한의 성능을 보장할 수 있다.