Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- mco
- object
- 배당성장
- FCF
- S&P500
- 제태크
- 오버라이딩
- 금리인하
- 그리디 알고리즘
- 알고리즘
- 현금흐름표
- 백준
- 객체지향
- javascript
- 접근제어자
- 무디스
- 금리인상
- StringBuffer
- 자바
- 주린이
- 잉여현금흐름
- etf
- 미국주식
- 다형성
- XLF
- 인플레이션
- Java
- 프로그래머스
- 기업분석
- 주식
Archives
- Today
- Total
오늘의하루
org.hibernate.loader.MultipleBagFetchException 원인 및 해결 본문
예외 발생 이유
이 예외는 Fetch Join을 할 때 발생하게 되는데 원인은 2개 이상의 컬렉션이 있는 상태에서 Fetch Join을 하는 경우에 발생하게 된다.
어쩌다 발생했을까?
C Entity와 B Entity는 N:1 관계이고 B Entity와 A Entity는 N:1 관계이고 모두 지연 로딩(LAZY)로 되어있다.
A Entity에서 특정 Id값으로 조회하여 조회되는 데이터를 Json 형식으로 보내려고 했다.
처음에 별 생각 없이 A Entity 자체를 보내게 되었는데 이때 Stack Overflow가 발생하고 넘어간 데이터를 보니 재귀현상이 발생하고 있었고 이 문제를 해결하기 위해 Fetch Join을 사용하면서 발견했다.
해결 방안
- 쿼리를 분리하자!
- 여러 개의 컬렉션을 가져와야 할 경우, 두 개의 별도의 쿼리를 실행하여 각각의 컬렉션을 가져올 수 있습니다.
- Fetch Join 대신 배치 조회 사용하자!
- 페치 조인 대신 배치 조회(batch fetching)를 사용하여 연관된 엔티티를 일괄로 가져올 수 있습니다. 이는 여러 개의 컬렉션을 패치 조인으로 가져오는 대신 엔티티 식별자를 사용하여 한 번에 여러 엔티티를 한꺼번에 가져오는 것입니다.
- Entity를 DTO로 변환하자!
- 이 방법은 지나가면서 보게 된 글이 떠올라서 해본 방법이며 이 방법이 성능에 좋은지는 현재 알 수 없지만 이 방법으로도 해결이 가능하다. 해당 방법은 Entity와 DTO를 별도로 만들어서 Entity를 DTO로 변환 시켜주면 지연 로딩으로 나가지 않았던 쿼리들이 나가기는 하지만 해당 문제를 해결할 수 있었다.
최종적으로 어떻게 했을까?
Hibernate에 대해 검색하던 도중 통계자료를 보여주는 hibernate.generate_statistics라는 걸 알게 되었다.
해당 옵션을 활성화 한 후 비교한 결과이다.
- No Fetch Join & All Entity Convert DTO
- 준비 및 실행 시간 : 0.0024989 초
- 총 쿼리 개수 : 4 개
- ONE Fetch Join & All Entity Convert DTO
- 준비 및 실행 시간 : 0.0015834 초
- 총 쿼리 개수 : 3 개
해당 통계가 정말 성능를 완벽하게 나타내는지는 아직 알 수 없지만 우선 1개의 컬렉션만 Fetch Join을 한 후 나머지 1개는 지연 로딩 상태로 두고 DTO로 변환하는것으로 결정하였다.
결정하게 된 계기는 우선 쿼리 수가 1개지만 줄었으며 준비 및 실행시간도 평균적으로 약 34~36%정도 빠르게 나타났기 때문이다.
'Spring > JPA' 카테고리의 다른 글
Comments