영속성 컨텍스트로 JPA가 내부적으로 돌아가는 구조를 알아보자
영속성 컨텍스트를 공부하기 전 잠깐 엔티티 매니저에 대해 알아보자

웹 애플리케이션 개발시 Entity Manager Factory 를 통해 고객의 요청이 들어올 때마다 Entity Manager 를 생성한다
Entity Manager는 내부적으로 데이터베이스 커넥션을 이용해서 데이터베이스를 사용한다.
그럼 영속성 컨텍스트는 뭐지?
EntityManager.persist 는 영속성 컨텍스트에 저장한다는 의미다 (db저장 x)엔티티에는 생명주기가 있다

이에 대해서 자세히 알아보자
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
//이제 작업을 할 부분
} catch (Exception e) {
tx.rollback();
System.out.println("err : " + e);
} finally {
em.close();
emf.close();
}
}

Member member = new Member();
member.setId(100L);
member.setName("Hello JPA");
엔티티 매니저 안의 영속성 컨텍스트 안에서 관리되는 상태

객체 아래에 아래와 같은 코드를 추가해본다
System.out.println("===BEFORE===");
em.persist(member);
System.out.println("===AFTER===");
===BEFORE===
===AFTER===
Hibernate:
/* insert hellojpa.Member
*/ insert
into
Member
(name, id)
values
(?, ?)

EntityManager.persist 를 함em.persist 를 할 때 쿼리가 날라간 것이 아니다em.persist 를 입력하면 영속성컨텍스트에 쿼리문이 저장되는것이다tx.commit 을 입력해야 영속성 컨텍스트에 저장되어 있던 쿼리문이 DB에 전송되서 실행되는 것이다.detach 를 하면 영속성 컨텍스트에서 지워진다remove 를 하면 db에서 삭제된다영속성 컨텍스트 내부에는 1차캐시 라는 것을 가지고 있다.
select를 하기 전에 영속성컨텍스트에서 1차캐시를 조회한다음 값을 가져온다
아래에 다음의 코드를 추가해보고 실행해보자
//비영속 상태
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//엔티티를 영속, 1차 캐시에 저장됨
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, 100L);
System.out.println("findMember.id = " + findMember.getId());
System.out.println("findMember.getName() = " + findMember.getName());
===BEFORE===
===AFTER===
findMember.id = 100
findMember.getName() = Hello JPA
Hibernate:
/* insert hellojpa.Member
*/ insert
into
Member
(name, id)
values
(?, ?)

EntityManager(영속 컨텍스트) 안에는 1차캐시가 있다.
1차캐시 안에는 id와 entity가 있다
id는 member의 아이디
entity는 entity의 값, member 객체가 담긴다

우선 캐시에서 찾은 후 캐시에 없으면 DB에서 조회를 한다
DB조회를 하면 다시 1차캐시에 저장하게 된다.
트랜젝션이 끝나면 같이 종료가 된다
Member a Member bMember a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b); //동일성 비교 true
Member a) 에는 DB에서 조회 후 1차캐시에 저장된다Member b) 에는 1차 캐시에서 가져온다
Member member1 = new Member(150L,"A");
Member member2 = new Member(160L,"B");
em.persist(member1);
em.persist(member2);
System.out.println("=====================");
tx.commit();
결과를 보면 commit을 한 순간에 쿼리문이 나가는 것을 확인할 수 있다.
영속성컨텍스트에는 1차캐시 외에도 쓰기지연 SQL 저장소라는 곳이 있다. 실행될 SQL문들이 저장되는 공간.

persist를 하면 1차캐시에 저장되면서 쓰기지연 SQL 저장소에서 실행될 SQL 문이 저장된다.em.persist를 한다고 해서 DB에 저장되는 것이 아니다.
tx.commit 하는 순간 flush되고 쿼리문이 실행되어 commit이 된다.DB에 한번에 보낼 수 있다.
<property name="hibernate.jdbc.batch_size" value="10"/>
를 입력하면 기다렸다가 10개를 한번에 보낼 수 있다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
//[드랜잭션] 커밋
transaction.commit();
em.update(member) 가 없을까?em.persist(member) 는 필요 없을까?
Member memberA = em.find(Member.class, “memberA");
em.remove(memberA); //엔티티 삭제
Member member = new Member(200L, "member200");
em.persist(member);
em.flush();
System.out.println("=========");
tx.commit();
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//중간에 JPQL 실행
query = em.createQuery("select m from Member m", Member.class);
List<Member> members= query.getResultList();
em.setFlushMode(FlushModeType.COMMIT)
FlushModeType.AUTOFlushModeType.COMMITem.detach(entity)em.clearem.close개인 git에 가면 전체 코드를 확인 할 수 있습니다