본문 바로가기
스프링 부트/Error-Log

[Error-Log] MultipleBagFetchException 해결법

by illlilillil 2022. 4. 16.

발단: 예전에 프로젝트를 진행하다가 EntityGraph를 사용해 Nested된 클래스들을 가져오는 코드를 짰었다. 그러나 메소드를 실행하는 과정에서 MultipleBagFetchException 예외가 터졌다. 원인은 여러 개의 oneToMany 관계를 가져와서였다.

 

Bag이란?

Hibernate에는 Bag이라는 컬렉션 타입이 있다. 자바 프레임워크가 아닌 요소이며 List와 비슷하게 중복 요소를 포함하나 순서가 보장되진 않는 컬렉션이다.

스프링 JPA에서는 기본적으로 컬렉션을 사용해 Many 관계를 매핑한다. Hibernate는 이러한 컬렉션을 Hibernate에서 만든 컬렉션으로 감싼다.

List -> PersistentBag

Set -> PersistentSet

Map -> PersistentMap

 

해결법

1. 일대다 타입을 List에서 Set으로 바꾸면서 해결했다. 중복을 허용하지 않기 때문에  중복 등록이 발생하지 않는다.

LinkedHashSet -> 순서 보장을 위해 linked로 선언해줘야 한다.

private Set<Subject> list = new LinkedHashSet<>();

2. Distinct를 사용해서 중복을 제거한다.

3. Hibernate default_batch_fetch_size 옵션 조정 -> 1000으로 권장한다. 해당 옵션을 주게 되면 자식 컬렉션들의 조회를 하나로 줄일 수 있다. 부모 키를 가지고 in절로 묶어버리기 때문에 가능하다. 따라서 1000을 주게 되면 최대 1000개의 부모 키를 가지고 조회를 수행하게 되어 쿼리가 많아지면 많아질수록 엄청난 효과를 볼 수 있다.

 

 

 

참고 자료 

 

MultipleBagFetchException 발생시 해결 방법

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

jojoldu.tistory.com

 

댓글