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이 발생하는 것이다.

해결책

  1. 지연로딩이 아닌 즉시로딩(Eager Loading)을 사용하는 방법이 있다.

    즉시로딩으로 객체를 조회할 때 연관된 모든 객체를 불러온다.

    연관관계 매핑을 하는 어노테이션(ex @OneToMany)에 fetch = FetchType.EAGER 프로퍼티를 추가하면 된다.

    즉시로딩이 필요없을 때도 실행된다면 애플리케이션의 성능이 떨어질 우려가 있다.

    그래서 추천하는 방법은 아니다.

  2. LazyInitializationException이 발생하는 메소드에 @Transactional을 붙인다.

    Hibernate의 session은 트랜잭션이 동작하는 동안 유지된다.

    그래서 session이 조기에 끊기는 것을 방지할 수 있다.

    이 방법을 추천한다.

키워드

지연로딩, 즉시로딩, 프록시 객체, Hibernate Session

참고자료 https://www.baeldung.com/hibernate-initialize-proxy-exception