Spring/JPA
(JPA) could not initialize proxy - no Session (2)
주누
2022. 11. 20. 21:19
영속성 컨텍스트 생성
OSIV 일 때 최초 요청 시 (컨트롤러 접근 시) 영속성 컨텍스트를 미리 생성한다.
OSIV가 아닐 때 트랜잭션 요청 시 영속성 컨텍스트를 생성한다.
OSIV 일때
인터셉터 영역에서 미리 영속성 컨텍스트를 생성해둔다.
생성 시 Map 형태로 생성을 하는데 Key 값은 영속성 컨텍스트이며 Value 값으로는 영속성 컨텍스트를 Wrapping 한 EntityManagerHolder를 생성한다. 여기서 EntityManagerHolder는 영속성 컨텍스트뿐만 아니라 이에 따르는 부가정보를 가지고 있다.
EntityManagerHolder 생성
EntityManagerHolder 저장
OSIV 아닐 때
미리 영속성 컨텍스트를 생성해 두는 것이 아닌 트랜잭션 시작 시점에 영속성 컨텍스트를 생성한다.
EntityManagerHolder 생성
- EntityManagerHolder 저장 또한 OSIV 일 때와 동일하다.
영속성 컨텍스트 해제
영속성 컨텍스트의 생성에 대해서 알아보았으니 영속성 컨텍스트의 해제에 대해서 알아보자
OSIV일 땐 요청 시점까지 영속성 컨텍스트를 유지해야 하니 해제를 하면 안 되고
OSIV가 아닐 땐 트랜잭션 종료 시점에 영속성 컨텍스트를 해제해야 한다. 이를 코드를 통해 확인해보자 이에 대한 모든 과정은
아래 클래스에서 일어난다.
JpaTransactionManager
OSIV 일 때
NewEntityMangerHolder 여부를 통해 영속성 컨텍스트 해제 여부를 판단하는데
OSIV 일 때는 NewEntityMangerHolder가 false 이기 때문에 트랜잭션 종료 시점에 영속성 컨텍스트를 해제하지 않는다.
JpaTransactionManager - doCleanupAfterCompletion
OSIV 아닐 때
OSIV 일때는 NewEntityMangerHolder가 false 이기 때문에 트랜잭션 종료 시점에 영속성 컨텍스트를 해제한다.
JpaTransactionManager - doCleanupAfterCompletion
TransactionSynchronizationManager - 영속성 컨텍스트 해제
- EntityManger 생성 시 Map에 저장해두었던 키값을 해제한다.
정리
이번 장에서 영속성 컨텍스트의 생성시점과 종료 시점을 코드를 통해서 확인해 보았다.
OSIV 일 때 DispatcherServlet 시점에 인터셉터를 통해서 미리 영속성 컨텍스트를 생성해두고 이를 요청이 종료하는 시점까지 해제하지 않는다.
이로 인해서 종료 시점까지 해당 엔티티는 Persisted 상태이기 때문에 조회를 하여도 아무 문제가 없다.
반면 OSIV가 아닌 경우 트랜잭션 시작 시점에 영속성 컨텍스트를 생성하고 트랜잭션 종료 시점에 영속성 컨텍스트를 종료한다.
이로 인해서 다음 레이어로 넘어가는 시점에 엔티티는 Detached 된 상태가 되며 해당 엔티티를 조회하면 could not initialize proxy를 마주하게 된다.
오늘도 나의 포스팅이 많은 분들에게 도움이 되길 바라며 포스팅을 마치도록 하겠다.