LazyInitializationException 처리하기 - woowacourse-teams/2021-gpu-is-mine GitHub Wiki
지금 이 문서를 읽는 당신.
LazyInitializationException: ... could not initialize proxy - no Session
이 예외가 발생했을거라 생각한다.
원인
JPA에는 두가지 FetchType이 있고, 연관관계 어노테이션에 따라 default FetchType이 다르다.
@ManyToMany
, @OneToMany
는 기본이 Lazy(지연로딩)이다.
@ManyToOne
, @OneToOne
는 기본이 Eager(즉시로딩)이다.
이름에서 유추할 수 있듯이 LazyInitializationException
은 Lazy일 때 발생하는 문제다.
지연로딩 상황을 가정해보자.
객체A안에 객체B가 있다면 JPA는 객체A를 조회할 때 객체B를 Proxy(프록시) 객체로 가져온다.
객체B는 실제 사용될 때 조회가 된다.
Hibernate에는 DB와 연결하는 session 있다.
이 session이 유지되는 동안 지연로딩이 가능하다.
하지만 session이 끊긴 후 지연로딩을 하면 LazyInitializationException
이 발생하는 것이다.
해결책
-
지연로딩이 아닌 즉시로딩(Eager Loading)을 사용하는 방법이 있다.
즉시로딩으로 객체를 조회할 때 연관된 모든 객체를 불러온다.
연관관계 매핑을 하는 어노테이션(ex
@OneToMany
)에fetch = FetchType.EAGER
프로퍼티를 추가하면 된다.즉시로딩이 필요없을 때도 실행된다면 애플리케이션의 성능이 떨어질 우려가 있다.
그래서 추천하는 방법은 아니다.
-
LazyInitializationException
이 발생하는 메소드에@Transactional
을 붙인다.Hibernate의 session은 트랜잭션이 동작하는 동안 유지된다.
그래서 session이 조기에 끊기는 것을 방지할 수 있다.
이 방법을 추천한다.
키워드
지연로딩, 즉시로딩, 프록시 객체, Hibernate Session
참고자료 https://www.baeldung.com/hibernate-initialize-proxy-exception