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
- StringBuffer
- javascript
- 미국주식
- 객체지향
- 그리디 알고리즘
- 백준
- 주식
- 금리인상
- 주린이
- 자바
- 프로그래머스
- S&P500
- object
- mco
- etf
- Java
- FCF
- 배당성장
- 제태크
- 기업분석
- 인플레이션
- 접근제어자
- 잉여현금흐름
- 다형성
- 무디스
- 현금흐름표
- XLF
- 오버라이딩
- 금리인하
- 알고리즘
Archives
- Today
- Total
오늘의하루
[JPA] LazyInitializationException 발생! 본문
예외 발생 이유
세션이 사라진 후 지연 로딩(LAZY) 상태에서 프록시 초기화가 불가능하기 때문에 발생하는 예외
지연 로딩 ( FetchType.LAZY )
지연 로딩을 하는 이유는 JPA에서 발생하는 문제 중 가장 유명한 N + 1 문제를 해결하기 위함이다.
지연 로딩은 한번에 연관된 데이터까지 한번에 불러오는 것이 아닌 연관된 데이터를 필요한 시점에 그때 그때 불러오는 것이다.
그래서 왜 지연 로딩을 쓰는가?
예를 들어 Member과 Team테이블이 있고 Member와 Team는 N:1 관계가 있다.
이때 즉시 로딩(EAGER)을 하게 된다면 Team을 조회 시 해당 Team을 가진 모든 Member를 하나씩 조회하게 된다.
분명 Team 1개를 조회했는데 Team에 속한 Member N개의 조회 쿼리가 나가는 문제를 N + 1 문제라고 하며 이런 문제를 지연 로딩(LAZY)로 쉽게 해결이 가능하기 때문이다.
해결 방안
- @Transactional Annotation
- Fetch Join
- @EntityGraph
@Transactional ✔
해당 예외의 근본적인 문제는 영속성 컨텍스트가 종료되고 트랜젝션이 끝났을 때 일어나는 예외이기 때문에 해당 문제를 근복적으로 해결할 수 있는 가장 좋은 해결 방안이다.
Fetch Join
Fetch Join은 JPQL에서 성능 최적화를 위해 제공하는 Join의 종류이다.
이는 연관된 Entity와 Collection을 한번에 조회할 수 있도록 해주는 기능이다.
Fetch Join을 사용하는 경우 Join 대상에는 별칭을 줄 수 없다.
// 해당 내용은 JPA 표준에서는 지원하지 않지만
// Hibernate 및 몇몇 구현체는 별칭을 지원하기 때문에 오류가 발생하지 않는다.
[❌] select t from Team t JOIN FETCH t.members m
[⭕] select t from Team t JOIN FETCH t.members
@EntityGraph
EntityGraph는 즉시 로딩(EAGER)와 다를 바 없지만 Distinct 설정이 가능하다는 장점이 있다.
결국 Left Outer Join으로 데이터를 읽어오게 된다.
// Member의 FetchSize는 LAZY이다.
public interface MemberRepository extends JpaRepository<Member, Long>{
@EntityGraph(attributePaths = {"team"})
List<Member> findEntityGraph();
}
select
member0_.member_id ~,
team1_.team_id ~,
member0_.username ~,
member0_.team_id ~,
team1_.name
from
member member0_
left outer join
team team1_ on member0_.team1_id = team1_.team_id
'Spring > JPA' 카테고리의 다른 글
Comments