엔티티 매니저
@Entity 어노테이션을 달고 있는 Entity 객체들을 관리하며 실제 DB 테이블과 매핑하여 데이터를 조회/수정/저장 하는 중요한 기능을 수행한다. EntityManager는 PersistenceContext라는 논리적 영역을 두어, 내부적으로 Entity의 생애주기를 관리한다.
영속성 컨텍스트
- 엔티티를 영구 저장하는 환경이라는 뜻이다.
- 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스 역할을 한다.
- 엔티티 매니저를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.
em.persist(member); : 엔티티 매니저를 사용해 회원 엔티티를 영속성 컨텍스트에 저장한다는 의미이다.
- 영속성 컨텍스트의 특징
- 엔티티 매니저로 생성할 때 하나 만들어진다. (싱글톤)
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근하고 관리할 수 있다.
- 영속성 컨텍스트는 동일한 Transaction 내에서 모든 객체들을 관리한다.
엔티티의 생명주기
- 비영속 : 영속성 컨텍스트와 전혀 관계가 없는 상태
- 영속 : 영속성 컨텍스트에 저장된 상태
- 준영속 : 영속성 컨텍스트에 저장되었다가 분리된 상태
- 삭제 : 삭제된 상태

코드와 함께 보기
- 비영속 : 엔티티 객체를 생성했으나 아직 영속성 컨텍스트에 저장하지 않은 상태
Member member = new Member();
- 영속 : 엔티티 매니저를 통해서 영속성 컨텍스트에 저장한 상태를 말하며 영속성 컨텍스트에 의해 엔티티가 관리됨.
em.persist(member);
- 준영속 : 더 이상 영속성 컨텍스트가 관리하지 않으면 준영속 상태가 된다.
- 1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩을 포함한 영속성 컨텍스트가 제공하는 어떠한 기능도 동작하지 않는다.
- 식별자 값을 가지고 있다.
em.detach(member);
em.claer();
em.close();
- 삭제 : 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다.
em.remove(member);
참고로 "삭제"의 경우 영속성 컨텍스트에서는 제거되지만 Java 입장에서 GC의 대상이 되는 것은 아니다.
영속성 컨텍스트의 특징
- 영속성 컨텍스트의 식별자 값
- 영속성 컨텍스트는 엔티티를 식별자 값으로 구분한다. 따라서 영속 상태는 식별자 값이 반드시 있어야 한다.
- 영속성 컨텍스트와 데이터베이스 저장
- jpa는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영하는데 이를
Flush라고 한다.
영속성 컨텍스트가 엔티티를 관리하면…
-
1차 캐시→ DB에 접근할 필요가 없다.
- 영속성 컨텍스트 내부에는 1차 캐시가 존재하는데, 영속 상태의 엔티티를 여기에 저장한다. 1차 캐시의 키는 식별자 값(데이터베이스의 기본 값)이고 값은 엔티티 인스턴스이다. 다음과 같이 조회한다.
Member member = em.find(Member.class, "member1");
-
동일성 보장
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.print(a==b)
참고로 ==가 성립하려면 주소값까지 같아야 함.
-
트랜잭션을 지원하는 쓰기 지연
- 바로바로 SQL문이 발생하지 않고 엔티티 매니저는 트랜잭션을 커밋하기 직전까지 내부 쿼리 저장소에 SQL문을 저장하고 커밋할 때 DB 한번에 전송한다.
-
변경 감지
- jpa로 엔티티를 수정할 때는 단순히 엔티티를 조회해서 값을 변경해주기만 하면 된다. 따로 저장할 필요가 없다. 어떻게 이게 가능하나?
- 변경 감지의 흐름?
- 트랜잭션을 커밋하면 엔티티 매니저 내부에서 flush가 호출된다
- 엔티티와 스냅샷을 비교하여 변경된 엔티티를 찾는다
- 변경된 엔티티가 있으면 수정 쿼리를 생성하여 쓰기 지연 SQL 저장소(Action Queue)에 저장한다
- 쓰기 지연 저장소의 SQL을 flush한다
- 데이터베이스 트랜잭션을 커밋한다.
- 물론 당연히 영속된 엔티티만 변경 감지가 가능하다.
Flush
영속성 컨텍스트의 변경 내용을 DB에 반영한다. (DB와 동기화한다.)
- Flush 하는 방법
em.flush()
- 트랜잭션 커밋 시 자동호출
- JPQL 쿼리 발생 시 자동호출