트랜잭션 범위의 영속성 컨텍스트
- 스프링이나 J2EE 컨테이너 환경에서는 컨테이너가 제공하는 전략을 따라야 한다.
- 스프링은 트랜잭션 범위의 영속성 컨텍스트 전력이 기본이다.
- 같은 트랜잭션 안에서는 같은 영속성 컨텍스트를 사용한다.
- 컨트롤러나 뷰같은 프리젠테이션 계층에서는 준영속상태가 된다.
- 그러므로 지연로딩을 시도하면 예외가 발생한다.
- 해결법
- 뷰가 필요한 엔티티를 미리 로딩해두는 방법
- OSIV를 사용해서 엔티티를 항상 영속 상태로 유지하는 방법
뷰가 필요한 엔티티를 미리 로딩해두는 방법
- 글로벌 페치 전략 수정(
fetchType.EAGER
) - JPQL 페치 조인
- 강제로 초기화
OSIV
- Open Session In View(JPA에서는 OEIV(Open EntityManager In View))
- 영속성 컨텍스트를 뷰까지 열어둔다.
과거 OSIV
- 서블릿 필터나 스프링 인터셉터에 트랜잭션 열고 닫기
- 프레젠테이션 계층에서도 엔티티를 변경할 수 있는 단점이 생김
- 해결법
- 읽기 전용 인터페이스 제공
- 엔티티 레핑
- DTO 반환
스프링이 제공하는 OSIV
spring-orm
- 다양한 OSIV 클래스 제공
OpenSessionInViewFilter
OpenSessionInViewInterceptor
OpenEntityManagerInViewFilter
OpenEntityManagerInViewInterceptor
- 비즈니스 계층에서 트랜잭션을 사용하는 OSIV
※ 출처: https://www.slideshare.net/sungjaepark121/ss-71171382
왜 프레젠테이션 계층에서 수정을 해도 반영이 되지 않을까?
- 서블릿 필터나 인터셉터에서는 플러시를 하지 않고 엔티티매니저를 종료시킨다.
- 강제로 플리쉬를 호출해도 트랜잭션 범위 밖이기 때문에
TransactionRequiredException
이 발생한다.
하지만, 데이터 변경 이후에 트랜잭션 범위에 포함되는 비즈니스로직이 실행된다면 수정된 데이터가 반영되므로 주의하자!