김영한 님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'를 듣고 적은 글 입니다.

고객의 요청이 올때마다 EntityManager를 생성한다. 이를 통해 디비 접근할 수 있다.
엔티티 매니저 안에 영속성 컨텍스트 공간이 존재한다고 생각하면 된다.
JPA를 이해하는데 가장 중요한 용어이다. 영속성 컨텍스트는 논리적인 개념으로 실제 눈에 보이진 않는다. 앞서 이야기 한 것 처럼 엔티티 매니저를 통해 영속성 컨텍스트에 접근가능하다.

Member member= new Member();
member.setId("member1");
member.setUsername("회원1");
단순 member 객체만 생성했기에 JPA와 전혀 관련이 없다.
Member member= new Member();
member.setId("member1");
member.setUsername("회원1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
//객체 저장(영속)
em.persist(member);
멤버 객체 생성 후 엔티티 매니저를 얻어와 persist()를 하면 영속 컨텍스트 안에 멤버 객체가 들어가게 된다.
하지만 이때 DB에 저장되진 않는다. 커밋 이후에 쿼리가 날아가기 때문이다.
em.detach(member)을 통해 회원 엔티티를 컨텍스트에서 분리해 준영속 상태로 만들수도 있고 em.remove(member)를 사용해 객체를 삭제할 수도 있다.
Member member= new Member();
member.setId("member1");
member.setUsername("회원1");
//1차 캐시에 저장
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");

영속성 컨텍스트는 1차 캐시라는것을 가지고 있다. 데이터 조회시 DB 먼저 조회하는게 아닌 1차 캐시를 조회해서 캐시 값을 가져온다.

그런데 DB에는 있고 1차캐시에는 없으면 디비에서 조회한 후 1차 캐시에 저장하고 캐시를 반환한다.
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b); //동일성 비교 true
1차 캐시로 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.
영속 컨텍스트 안에 쓰기 지연 SQL 저장소 존재한다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않음
//커밋하는 순간 INSERT SQL 날림
transaction.commit();
persist()를 하면 1차 캐시에 저장하고 쓰기 지연 SQL 저장소에 INSERT SQL을 생성해놓는다. commit() 이후 DB에 만들어놓은 INSERT SQL을 날린다.
find()로 멤버 변수 찾아서 이름이나 아이디 바꿔준 뒤 persist() 적을 필요가 없다. 자동으로 업데이트 쿼리가 나가기 때문이다. 이를 Dirty Checking 이라고 한다.

스냅샷이라는 걸 찍어두는데 이때 엔티티랑 스냅샷을 비교한다. 비교하고 바뀐게 있으면 UPDATE 쿼리를 쓰기 지연 SQL 저장소에 만들어 둔다. 그리고 디비에 반영해 커밋한다.
영속성 컨텍스트의 변경내용을 데이터베이스에 반영한다.
플러시는 영속성 컨텍스트를 비우지 않는다.
트랜잭션이라는 작업단위가 매우 중요하다. (커밋 직전에만 동기화하면 된다)
FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시(DEFAULT)FlushModeType.COMMIT : 커밋할 때만 플러시em.flush() : flush() 를 사용해도 1차캐시는 그대로 유지된다. 쓰기 지연 SQL 저장소에 위치한 쿼리들 중 변경된 애들이 데이터베이스에 반영이 되는 과정이라고 생각하면 된다.
트랜잭션 커밋
JPQL 쿼리 실행 : JPQL 실행 시 무조건 flush() 를 날려서 DB에서 쿼리문을 사용할 수 있도록 한다. 아직 쿼리문에 안날아갔는데 INSERT문 으로 조회하면 오류가 발생하기 때문이다.
영속 상태의 엔티티가 영속성 컨테스트에서 분리한 것을 말한다.
준영속 상태가 되면 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.
em.detach(entity) : 특정 엔티티만 준영속 상태로 전환
detach()를 하게되면 이름을 바꿔도 업데이트 쿼리를 날리지 않는다. 준영속 상태가 되서 더이상 JPA 에서 관리하지 않기 때문이다.
em.clear() : 영속성 컨텍스트를 완전히 초기화
1차 캐시를 완전히 지워버린다.
em.close() : 영속성 컨텍스트 종료