MultipleBagFetchException(두개의 Fetch Join)

2024. 10. 8. 13:40·Java & Spring/트러블슈팅

- 문제상황

        List<Todo> results = jpaQueryFactory
                .selectFrom(todo)
                .leftJoin(todo.managers).fetchJoin()
                .leftJoin(todo.comments).fetchJoin()
                .where(condition)
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();
  • todo조회 시 manager와 comment의 개수를 출력하면서 N+1문제를 해결하기 위해 Fetch Join을 연속으로 두개 사용
  • MultipleBagFetchException 발생
    -> 2개 이상의 OneToMany 자식 테이블에 Fetch Join을 선언했을때 발생
    MultipleBagFetchException의 원인
    Hibernate는 여러 개의 List 타입 @OneToMany 또는 @ManyToMany 관계를 Fetch Join으로 동시에 로딩할 때, 내부적으로 "중복된 레코드"를 제거하는 방식 때문에 발생, List는 순서를 보장해야 하기 때문에, 데이터베이스에서 조회된 결과를 그대로 유지해야 하며, 중복 제거 시 복잡성이 증가 이로 인해, Hibernate는 여러 컬렉션을 List로 Fetch Join하는 경우 예외를 던지게됨.

 

- 해결방법

 

1. 객체수가 많은 comment는 fetchjoin으로 대비 작은 manager은 BatchSize로 해결

   List<Todo> results = jpaQueryFactory
                .selectFrom(todo)
                .leftJoin(todo.managers)
                .leftJoin(todo.comments).fetchJoin()
                .where(condition)
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();
           
    // Todo Entity
    public class Todo extends Timestamped {             
        @OneToMany(mappedBy = "todo", cascade = CascadeType.PERSIST)
        @BatchSize(size = 10)
        private List<Manager> managers = new ArrayList<>();
    }

 

2. OneToMany부분을 Set으로 받아 처리

    @OneToMany(mappedBy = "todo", cascade = CascadeType.REMOVE)
    private Set<Comment> comments = new HashSet<>();

    @OneToMany(mappedBy = "todo", cascade = CascadeType.PERSIST)
    private Set<Manager> managers = new HashSet<>();

'Java & Spring > 트러블슈팅' 카테고리의 다른 글

@Transactional(propagation = Propagation.REQUIRES_NEW)  (0) 2024.10.10
Self-invocation(자기 호출)  (0) 2024.09.05
'Java & Spring/트러블슈팅' 카테고리의 다른 글
  • @Transactional(propagation = Propagation.REQUIRES_NEW)
  • Self-invocation(자기 호출)
DJ.Kang
DJ.Kang
백엔드 개발 기록 블로그
  • DJ.Kang
    DJ Hello World
    DJ.Kang
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 이론공부
      • 시스템설계
      • Java & Spring
        • TIL
        • 트러블슈팅
        • 고도화
        • 알고리즘
        • 코딩테스트
        • Java
        • Spring
        • Thymeleaf
      • 프로젝트
        • coin-trading
        • 트러블슈팅
      • Docker
      • DB
      • AWS
      • CI-CD
      • 웹
      • git & github
      • 구인공고분석
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    java super
    java
    데이터 크기
    프로그래머스 java 기초트레이닝
    java 멤버
    java 제어자
    java arrays.copyofrnage()
    java two-pointer
    java기초
    java 메서드
    java 세수의합
    Java 생성자
    데이터 타입
    자료구조
    java 에라토스테네스의 체
    java enhance switch
    java 유클리드 호제법
    개발로드맵
    Java this
    프로그래머스 java 기초 트레이닝
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
DJ.Kang
MultipleBagFetchException(두개의 Fetch Join)
상단으로

티스토리툴바