엔티티를 영구 저장하는 환경
애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스 같은 역할을 함.
엔티티 매니저(Entity Manager)를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리함.
EntityManager em;
Member member;
em.persist(member); // member를 영속성 컨텍스트에 저장
Member member = new Member();
em.persist(member);
준영속(detached): 영속성 컨텍스트에 저장되었다가 분리된 상태
detach
: 엔티티를 영속성 컨텍스트에서 분리해 준영속 상태로 만듦. (특정 엔티티를 준영속 상태로 만들 수 있음.)
clear
: 영속성 컨텍스트를 비움. (초기화)
close
: 영속성 컨텍스트를 종료함.
em.detach(member);
em.clear();
em.close();
em.remove(member);
+) transient: 덧없는, 무상한; 일시의, 순간적인
영속성 컨텍스트는 엔티티를 식별자 값으로 구분함.
영속 상태는 식별자 값이 반드시 있어야 함.
JPA는 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영함.
이를 flush
라고 함.
+) 플러시
영속성 컨텍스트의 변경 내용을 데이터베이스에 반영함. 영속성 컨텍스트의 엔티티를 지우는게 아니라 변경 내용을 데이터베이스에 동기화하는 것.
플러시 하는 법
em.flush()
영속성 컨텍스트 내부의 캐시를 1차 캐시라고 함.
영속 상태의 엔티티를 1차 캐시에 저장함.
1차 캐시의 키는 식별자 값(데이터베이스의 기본 키)이고 값은 엔티티 인스턴스임.
em.find(엔티티 클래스 타입, 식별자 값)
: 1차 캐시 안에 있는 데이터 조회Member member = em.find(Member.class, "member");
영속성 컨텍스트는 엔티티의 동일성을 보장함.
Member memberA = em.find(Member.class, "member");
Member memberB = em.find(Member.class, "member");
System.out.println(memberA == memberB); // true
+) JPA에서의 동일성과는 다른 개념이지만 연관될 수 있음.
JPA의 동일성은 두 인스턴스가 물리적으로 같은 객체인지를 판별하기 때문에 엔티티의 기본 키(PK)가 같은지를 기준으로 함. 물론 이는 영속성 컨텍스트도 마찬가지임.
++) 동일성과 동등성
==
equals()
Transactional write-behind
엔티티 매니저는 트랜잭션을 커밋하기 직전까지 내부 쿼리 저장소에 insert sql을 모아둠.
그리고 트랜잭션을 커밋할 때 모아둔 쿼리를 DB에 보냄.
이를 트랜잭션을 지원하는 쓰기 지연이라고 함.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // 트랜잭션 시작
// 다음 insert sql은 바로 데이터베이스로 보내지 않음.
em.persist(memberA);
em.persist(memberB);
transaction.commit(); // 트랜잭션 커밋
// 커밋하는 순간 insert sql을 보냄.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // 트랜잭션 시작
Member member = em.find(Member.class, "member");
member.setName("6720");
transaction.commit(); // 트랜잭션 커밋
조회한 엔티티를 수정함으로써 em.update(member)
가 있어야 할 것 같지만, 그러한 코드가 없어도 영속성 컨텍스트 내의 스냅샷과 엔티티를 비교해 변경된 엔티티가 있으면 update 쿼리를 자동으로 생성함. (해당 update 쿼리도 쓰기 지연이 될 수 있음.)
Lazy Loading
지연로딩은 연관 관계 매핑되어 있는 엔티티를 조회 시 우선 프록시 객체를 반환하고, 실제로 필요할 때 쿼리를 날려 가져오는 기능이며, 필요할 때 데이터를 가져오는 기능임.