송민준의 개발노트

[JPA] MultipleBagFetchException 본문

웹/JPA

[JPA] MultipleBagFetchException

송민준 2023. 1. 23. 23:57

원인

JPA로 개발하던 와중 연관관계 설정 후 테스트를 해보니 에러가 발생했다.

MultipleBagFetchException이 발생했는데

XToMany 관계를 설정하는데 있어 Eager Fetch를 사용할 경우 2개 이상의 List가 있으면 해당 Exception 이 발생한다.

(Lazy로 설정하더라도 fetch join을 실행할 경우 한번에 가져오니 Eager로 봄)

 

 

원인을 분석해보니 Hibernate는 내부적으로 컬렉션을 참조하고 있는 대상을 추적하고 관리하기 위해 List를 PersistentBag이라는 객체로 래핑하여 한다.

그런데 엔티티에서 동시에 두개 이상의 Bag을 가져오면 카디션곱이 발생하고 Hibernate는 올바른 항목에 올바른 열을 매핑할 수 없다고 한다. 그래서 MultipleBagFetchException이 발생하는 것이다.

 

 

그렇다면 어떻게 해야하는가?

1. List 대신 Set을 사용한다.

- 해당 접근 방식은 간단하지만 정렬이나 중복요소가 있을 경우에는 적절하지 않다.

- Set을 사용해도 된다면 1개는 List(Bag), 나머지는 Set으로 가능하다.(혹은 전부 Set)

 

2. 쿼리 분할

- 1개를 제외한 관계는 Lazy 로 분할해서 가져오기

- 쿼리를 분할하게 되면 Lazy 로드하는 부분에서 1:N 성능 문제가 발생할 수 있다.

  default_batch_fetch_size 옵션을 주면 in으로 조회가 되어 성능 개선이 될 수 있다.

  or @Fetch(value = FetchMode.SUBSELECT) 를 줘서 서브쿼리 형태로 조회

 

 

 

참고 블로그

https://jojoldu.tistory.com/457?fbclid=IwAR132BRMYHrL4D5Pu25YUglIcEN1FGTE2tacFcsVOPAT0MAzwoMX6Flzbe0 

 

MultipleBagFetchException 발생시 해결 방법

JPA의 N+1 문제에 대한 해결책으로 Fetch Join을 사용하다보면 자주 만나는 문제가 있습니다. 바로 MultipleBagFetchException 입니다. 이 문제는 2개 이상의 OneToMany 자식 테이블에 Fetch Join을 선언했을때 발

jojoldu.tistory.com

https://jerry92k.tistory.com/66

 

[JPA-Hibernate] Collection 타입은 PersistentBag 타입으로 래핑된다.

요약 하이버네이트에서는 컬렉션 타입을 org.hibernate.collection.internal.PersistentBag 인스턴스로 래핑하여 사용합니다. 이 때문에 Collection 타입에서 orphanRemoval 옵션 사용시 주의 해야합니다. [참고 - orph

jerry92k.tistory.com

https://www.baeldung.com/java-hibernate-multiplebagfetchexception

 

' > JPA' 카테고리의 다른 글

OSIV  (0) 2021.04.18
JPQL 조건식 및 함수 사용법  (0) 2021.04.04
JPA의 데이터 타입 분류  (0) 2021.03.11
영속성 전이(CASCADE)와 고아 객체  (0) 2021.03.09
지연 로딩, 즉시 로딩 총정리  (0) 2021.03.07