개요
JPA 쿼리를 통해 엔티티를 불러올 때 두 개 이상의 @OneToMany 관계를 갖는 엔티티를 함께 EAGER LOADING 할 때 아래와 같은 오류 메시지가 발생했습니다.
저 같은 경우 위와 같이 @OneToMany 관계가 다수인 엔티티를 FETCH JOIN을 통해 한 번에 불러오려고 할 때 MultipleBagFetchException 예외가 발생했습니다.
* SampleInput과 SampleOutput을 모두 fetch type EAGER로 변환한다고 해도 동일한 에러가 발생합니다.)
원인
위와 같은 예외가 발생하는 원인을 파악하기 위해서는 우선 Bag의 정의를 살펴봐야 합니다.
Bag은 중복된 요소를 허용하는 순서가 없는 컬렉션(MultiSet)이며 Java Collection에서는 Bag이 정의되어 있지 않기 때문에 Hibernate에서는 List를 Bag로 사용하고 있습니다.
Hibernate는 일반적으로 관계를 효율적으로 로드하기 위해 JOIN문을 사용하는데, Join은 일대다 관계에서 중복된 결과를 가져올 수 있습니다.
즉, 여러 개의 Bag을 함께 로드하면 중복된 결과가 발생할 수 있습니다.
또한, Bag은 순서가 보장되지 않기 때문에 여러 개의 Bag을 동시에 불러오면 @OrderBy 어노테이션으로 정의한 컬렉션의 순서가불일치할수 있습니다.
이러한 이유로 Hibernate는 두 개 이상의 @OneToMany 관계를 갖는 엔티티를 한 번에 불러오려고 시도할 때 MultipleBagFetchException을 발생시킵니다.
해결 방법
다시 정리하자면 MultipleBagFetchException 예외는 중복된 요소를 허용하는 순서가 없는 컬렉션을 동시에 여러 개 불러와 순서가 보장되지 않은 중복된 결과를 야기할 수 있기 때문에 발생합니다.
따라서 컬렉션을 List가 아닌 Set으로 변경한다면 중복이 허용되지 않고 우선순위를 정의해 주면 순서가 보장되므로 MultipleBagFetchException이 발생하지 않습니다.
Set 컬렉션과 @OrderBy 어노테이션 관련해서는 아래 블로그를 참고해 주세요.
https://velog.io/@csh0034/Spring-Data-JPA-Set-OrderBy
참고
https://perfectacle.github.io/2019/05/01/hibernate-multiple-bag-fetch-exception/
'DB > JPA' 카테고리의 다른 글
[JPA] 준영속(Detached) 상태 엔티티 수정하는 방법 (0) | 2023.05.07 |
---|---|
[JPA] JPQL 추가 정리 (0) | 2021.10.18 |
[JPA] JPQL 간단 정리 (0) | 2021.10.16 |
[JPA] 값 타입 정리 (0) | 2021.09.29 |
[JPA] 프록시와 연관관계 관리 정리 (0) | 2021.09.14 |