[springboot]JPA의 LazyInitializationException
코드
Optional<GuestBook> findGuestBook = guestBookRepository.findByUser(user); if( findGuestBook.isPresent() ) return findGuestBook.get().getGuestBookComments();
문제점
guestBookRepository를 통해 Entity "GuestBook"을 찾은 뒤 해당 객체에 접근하려고 할 시 LazyInitializationException 발생
- JPA에서 관리하는 세션이 종료된 후( 영속성 컨텍스트가 종료된 후 ) 관계가 설정된 엔티티를 참조하려고 할때 발생한다.
해결책
@Transactional의 성질
▶ 원자성(Atomicity)
: 한 트랜잭션 내에서 실행한 작업들은 하나로 간주한다. 즉, 모두 성공 또는 모두 실패.
▶ 일관성(Consistency)
: 트랜잭션은 일관성 있는 데이타베이스 상태를 유지한다. (data integrity 만족 등.)
▶ 격리성(Isolation)
: 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리해야한다.
▶ 지속성(Durability)
: 트랜잭션을 성공적으로 마치면 결과가 항상 저장되어야 한다
1. 현재 Service 단의 함수에 @Transactional 어노테이션을 사용하지 않고 더 상위 레이어인 Controller 단계의 함수에 @Transactional 어노테이션 사용
@GetMapping("/api/guestbook")
@Transactional
public ResponseEntity<ApiResponse<List<GuestBookDto>>> getGuestBooks(HttpServletRequest request){
...
}
2. Fetch join
-
Transactional의 경우
연관관계가 설정된 엔티티에 접근할 경우 추가쿼리가 매번 발생한다.
예를 들어, Member를 조회하고 그에 속한 Team을 조회할 경우 각 Member마다 DB에서 Team과 Join하여 찾아온다. 1000명의 Member에 대해 Team을 조회할 경우 +1000번의 쿼리 발생 -
Fetch Join이 이것을 해결해줌. 처음부터 Member를 조회할때 Team과 Join하여 가져와 가지고 있음. 이는 각 Member 별 Team을 조회하더라도 추가 쿼리가 발생되지 않기 때문에 1번의 쿼리로 모든 정보 조회가능
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m join fetch m.team ") // (1)
List<Member> findAllMembers();
}
3. @EntityGraph 어노테이션 사용 ( Fetch Join을 자동으로 해줌.)
-
연관관계가 있는 엔티티를 조회할 경우 지연 로딩으로 설정되어 있으면 연관관계에서 종속된 엔티티는 쿼리 실행 시 select 되지 않고 proxy 객체를 만들어 엔티티가 적용시킨다. 그 후 해당 프락시 객체를 호출할 때마다 그때그때 select 쿼리가 실행된다. 자세한 사항은 JPA의 지연 로딩에 관하여 찾아보자. 위 같은 연관관계가 지연 로딩으로 되어있을 경우 fetch 조인을 사용하여 여러 번의 쿼리를 한 번에 해결할 수 있다.
-
@EntityGraph는 Data JPA에서 fect 조인을 어노테이션으로 사용할 수 있도록 만들어 준 기능
@Repository
public interface GuestBookRepository extends JpaRepository<GuestBook,Long> {
@EntityGraph(attributePaths = { "guestBookComments" })
public Optional<GuestBook> findByUser(User user);
}
Author And Source
이 문제에 관하여([springboot]JPA의 LazyInitializationException), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@beanzinu/springbootJPA의-LazyInitializationException저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)