코진남

Transaction 범위의 영속성 컨텍스트 본문

BackEnd/JPA

Transaction 범위의 영속성 컨텍스트

woojin126 2022. 2. 1. 00:03

스프링 컨테이너의 기본 전략

트랜잭션 범위와 영속성 컨텍스트의 생존 범위가 같다는 뜻으로 트랜잭션을 시작할 때 영속성 컨텍스트를 생성하고 트랜잭션이 끝날 때 영속성 컨텍스트를 종료한다.

트랜잭션을 커밋하면 JPA는 먼저 영속성 컨텍스트를 플러시해서 변경 내용을 데이터베이스에 반영한 후에 데이터베이스 트랜잭션을 커밋한다

(예외가 발생하면 트랜잭션을 롤백하고 종료하면 플러시를 호출하지않는다.)

@Transaction 어노테이션, 트랜잭션 AOP

트랜잭션이 같으면 같은 영속성 컨텍스트 사용

트랜잭션이 다르면 다른 영속성 컨텍스트 사용

같은 엔티티 매니저를 사용해도 트랜잭션에 따라 접근하는 영속성 컨텍스트가 다르다.

스프링 컨테이너는 스레드마다 각각 다른 트랜잭션을 할당한다. 따라서 같은 엔티티 매니저를 호출해도 접근하는 영속성 컨텍스트가 다르므로 멀티스레드 환경에 안전하다.

준영속 상태와 지연 로딩

트랜잭션 범위의 영속성 컨텍스트 전략을 사용하면 트랜잭션이 없는 프레젠테이션 계층(Controller) 에서 엔티티는 영속 상태가 아닌 준영속 상태이다. 따라서 변경감지와 지연 로딩이 동작하지 않는다.

준영속 상태의 문제는 지연 로딩 기능이 동작하지 않는다는 점이다.

예를 들어 뷰를 렌터링 할 때 연관된 엔티티도 함께 조회했다고 가정했을 때, 아직 초기화하지 않는 프록시 객체를 사용하면 실제 데이터를 불러오려고 초기화를 시도하지만 준영속 상태이므로 지연 로딩을 할 수 없다.

해결 방법

뷰가 필요한 엔티티를 미리 로딩해 두는 방법

OSIV를 사용해서 엔티티를 항상 영속 상태로 유지하는 방법

뷰가 필요한 엔티티를 미리 로딩해두는 방법

- 글로벌 페치 전략 수정(즉시로딩)

- JPQL 페치조인

- 강제 초기화