영속성 컨텍스트란?
- Entity를 영구저장하는 환경으로 눈에 보이지 않는 논리적 개념
- EntityManager로 Entity를 저장, 조회하면 EntityManager는 영속성 컨텍스트에 Entity를 보관하고 관리
- EntityManager를 통해 영속성 컨텍스트에 접근 및 관리 가능
- EntityManger를 생성할 때 만들어짐
특징
식별자
- Entity를 식별자 값(@Id)으로 구분하므로 영속상태의 Entity는 반드시 식별자 값이 있어야 함
flush
- JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 Entity를 데이터베이스에 반영 (이 과정을 flush라 함)
1차 캐시
- 영속성 컨텍스트 내부에 존재하는 캐시(map)
- 영속 상태의 Entity는 모두 이곳에 저장(키 = 식별자, 값 = Entity 인스턴스)
- entityManager.find() 메서드를 호출하면 먼저 1차 캐시에서 entity를 찾고, 만약 1차 캐시에 없으면 데이터베이스 조회하여 1차 캐시에 저장하고 영속상태인 해당 객체를 반환
객체의 동일성 보장
Person p1 = entityManager.find(Person.class, 1);
Person p2 = entityManager.find(Person.class, 1);
p1 == p2
트랜잭션을 지원하는 쓰기 지연을 수행 (Transactional write-behind)
- EntityManager는 트랜잭션을 commit 하기 전까지 데이터베이스에 Entity를 저장하지 않고 영속성 컨텍스트 내부의 SQL 저장소에 생성 쿼리를 저장한다.
이 후 commit 하게 되면 저장해두었던 여러 쿼리를 데이터베이스에 보내는데, 이를 트랜잭션을 지원하는 쓰기 지연
이라 한다.
변경 감지 (Dirty Checking)
- JPA는 Update라는 메소드가 없고 변경을 감지하여 수정 쿼리를 생성
- 영속성 컨텍스트에는 이전 flush 때의 Entity 상태를 복사해 저장해둔 스냅샷이 존재
flush 시점에 스냅샷과 Entity를 비교해 변경된 Entity를 찾고, 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 저장
- 변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 Entity에만 적용
지연 로딩
- 실제 객체 대신 프록시 객체를 로딩해두고 해당 객체를 실제 사용할 때 영속성 컨텍스트를 통해 데이터를 불러오는 방법