영속성 컨텍스트란?
영속성 컨텍스트(Persistence Context)는 엔티티를 영구 저장하는 환경이다.
애플리케이션과 DB 사이에서 객체를 보관하는 가상 DB이기도 하다.
EntityManager.persist(entity)는 엔티티를 영속성 컨텍스트에 저장시키는 코드이다.

EntityManagerFactory는 매 요청마다 엔티티 매니저를 생성한다.
생성된 엔티티 매니저는 데이터베이스 커넥션을 통해 DB를 사용할 수 있다.
영속성 컨텍스트는 엔티티 매니저를 생성할 때 하나 만들어진다.
엔티티 매니저를 통해 영속성 컨텍스트를 접근하고 관리할 수 있다.
같은 트랜잭션 내에 있는 엔티티 매니저는 동일한 영속성 컨텍스트에 접근한다.
엔티티 생명주기
비영속 (new)
엔티티를 생성했지만 영속성 컨텍스트에 저장하지 않은 상태이다.
Member member = new Member();
영속 (managed)
영속성 컨텍스트에 저장되어 관리되는 상태이다.
트랜잭션이 commit되지 않았으므로, 바로 DB에 저장되지는 않는다.
em.persist(member);
준영속 (detached)
영속성 컨텍스트에 저장되었다가 분리된 상태이다.
더 이상 영속성 컨텍스트가 엔티티를 관리하지 않는다.
em.detach(member);
삭제 (removed)
엔티티를 영속성 컨텍스트와 DB에서 삭제한 상태이다.
em.remove(member);
영속성 컨텍스트의 이점
엔티티 조회
i) 1차 캐시에서 조회

영속성 컨텍스트 내부에 1차 캐시가 존재하며 key - value 형태로 저장된다.
key는 객체의 id, value는 Entity 객체이다.
Member member = new Member();
member.setId("member1");
em.persist(member);
ii) 데이터베이스에서 조회
1차 캐시에 id가 member2인 객체가 없으므로, DB에서 조회한다.
DB에서 조회한 member2를 1차 캐시에서 저장 후 반환한다.
Member findMember2 = em.find(Member.class, "member2");
1차 캐시에서 조회할 경우, DB에 select문 쿼리가 나가지 않는다. 아래 예시를 살펴보자
findMember1은 id가 101인 Member 객체이다.
해당 객체가 1차 캐시에 없으므로 DB에서 조회한다.
이 때 select 쿼리가 한 번 나간다.
DB에서 조회하고 반환할 때, id = 101인 Member 객체는 1차 캐시에 저장된다.
findMember2는 1차 캐시에 저장된 Member 객체와 동일하므로 1차 캐시에서 조회한다.
1차 캐시에서 조회하므로 select 쿼리가 나가지 않는다.
Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
tx.commit(); // select문 출력 시점
영속 엔티티의 동일성 보장
1차 캐시로 반복 가능한 읽기가 가능하다.
한 트랜잭션 내에서 키 값과 클래스가 같으면 동일한 객체이다.
Member m1 = em.find(Member.class, 101L);
Member m2 = em.find(Member.class, 101L);
System.out.println(m1 == m2); //true
트랜잭션을 지원하는 쓰기 지연
영속성 컨텍스트 내에는 1차 캐시 외에도 쓰기 지연 SQL 저장소가 존재한다.
em.persist(member)로 객체를 1차 캐시에 저장하면, insert 쿼리가 생성되어 쓰기 지연 SQL 저장소에 쌓인다.
트랜잭션 commit 시점에 쓰기 지연 SQL 저장소의 쿼리들이 DB로 flush 된다.

엔티티 수정 시 변경 감지
1차 캐시에서 엔티티와 스냅샷을 비교하여 update SQL을 생성한다.
트랜잭션 commit 시점에 DB로 update SQL이 flush 된다.
변경을 감지하기 때문에 엔티티 값을 수정 후 persist()가 불필요하다.
Member member = em.find(Member.class, 150L);
member.setName("zz");
//em.update();
//em.persist();
Reference
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
초급자를 위해 준비한 [웹 개발, 백엔드] 강의입니다. JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자
www.inflearn.com