[Jpa] 영속성 컨텍스트

JPA는 사용자 요청이 들어올 떄마다 EntityManagerFactory에서 EntityManager를 생성해줌

영속성 (Persistence)

데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성

영속성 컨텍스트

엔티티를 영구 저장하는 환경.

EntityManager를 이용해 Entity를 저장/조회 할 때 영속성 컨텍스트에 Entity를 보관하고 관리함.

영속성 컨텍스트는 논리적 개념으로 EntityManager를 통해 접근할 수 있음.

영속성 컨텍스트를 사용하는 이유

1. 1차 캐시

한 트랜잭션 내에서 사용 되는 캐시

entityManager.persist(entity); //1차 캐시에 저장
Entity a = entityManager.find(Entity.class, "entity1"); // 1차 캐시에서 조회
Entity b = entityManager.find(Entity.class, "entity2"); // DB에서 조회 후 캐시에 저장

엔티티를 조회하면 DB에서 조회하는 것이 아닌 먼저 1차 캐시에서 조회를 한다.

2. 동일성 보장

DB Isolation Level이 Read Commit이어도 어플리케이션에서 Repeatable Read 보장

Entity a = entityManager.find(Entity.class, "entity1");
Entity b = entityManager.find(Entity.class, "entity1");

a == b; //true

3. 트랜잭션을 지원하는 쓰기 지연

엔티티를 저장해도 내부적으로 버퍼에 저장이 되고 Flush가 이루어지는 시점에 DB에 저장이 됨.

4. 변경 감지

JPA가 1차 캐시에 저장될 때 스냅샷이 함께 생성되며, Flush가 이루어지는 시점에 스냅샷을 비교하여 변경사항이 있을 경우 UPDATE 쿼리를 실행함.

5. 지연 로딩

Flush : 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송

  • 영속성 컨텍스트를 비우지 않음.
  • 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화 하는 목적
  • 트랜잭션이라는 작업 단위가 중요. 커밋 직전에만 동기화 하면 됨

  • entityManager.flush()를 직접 호출하거나 트랜잭션 커밋 시점, JPQL 실행 시에 자동 호출 된다.

엔티티의 생명주기

entity-lifecycle

1. 비영속(new / trasient)

객체를 생성한 상태

Entity entity = new Entity();

2. 영속 (managed)

엔티티매니저를 통해 엔티티를 영속성 컨텍스트에 저장한 상태

entityManager.persist(entity);

3. 준영속 (detached)

영속 상태의 엔티티를 엔티티매니저가 관리하지 않는 상태

1. entityManager.detach(entity); // 특정 엔티티를 준영속 상태로 변경
2. entityManager.clear(); // 영속성 컨텍스트를 초기화
3. entityManager.close(); // 영속성 컨텍스트 종료

지연 로딩으로 관리되는 객체가 준영속 상태면 예외가 발생한다. (Service의 트랜잭션이 끝나고 Controller에서 Lazy load하는 경우)

4. 삭제

엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제

entityManager.remove(entity);