EntityManagerFactory를 통해 고객의 요청이 올 때 마다 EntityManager를 생성한다. EntityManager는 내부적으로 DB 커넥션을 활용해서 DB를 사용한다.
EntityManager.persist(entity)
엔티티의 생명주기
//비영속
Member member = new Member();
member.setId(100L);
member.setName("HelloJPA");
//영속
em.persist(member);
//준영속
em.detach(member);
//삭제
em.remove(member)
영속성 컨텍스트에는 id, Entity를 key, value로 갖는 1차 캐시가 있다. em.persist
로 1차 캐시에 저장하고 em.find
하면 1차 캐시에서 먼저 조회한다. db에는 있고 1차 캐시에는 없는 데이터는 먼저 1차 캐시를 찾아보고 없으면 db에서 조회해서 1차 캐시에 저장하고 반환한다.
영속성 컨텍스트는 동일성을 보장한다(같은 키값으로 꺼내면 ==
비교 시 true)
영속성 컨텍스트가 있어서 트랜잭션을 지원하는 쓰기 지연이 가능하다.
영속성 컨텍스트에는 쓰기 지연 SQL 저장소가 있어서 쿼리문이 쓰기 지연 SQL 저장소에 있다가 transaction.commit()
하면 flush가 되면서 DB에 쿼리문이 날라가고 커밋한다.
Member member1 = new Member(150L, "A");
Member member2 = new Member(160L, "B");
em.persist(member1);
em.persist(member2);
System.out.println("==================");
tx.commit();
또한 엔티티 수정 시 변경 감지가 가능하다.
Member member = em.find(Member.class, 150L);
member.setName("ZZZZZ");
tx.commit();
persist
로 저장해주지 않고 setName
으로 변경만 해도 알아서 UPDATE 쿼리가 나간다.
1차 캐시에 스냅샷이 있다. (영속성 컨텍스트로 최초로 읽어온 시점의 상태를 저장함)
JPA가 commit하는 시점에 내부적으로 flush()
가 호출된다.
그 때 엔티티랑 스냅샷을 비교한다. 바뀐게 있으면 쓰기 지연 SQL 저장소에 UPDATE 쿼리를 만들어서 DB예 반영하고 커밋한다.
DELETE도 마찬가지로 커밋 시점에 쿼리가 나간다.
영속성 컨텍스트의 변경 내역을 DB에 반영하는 것
영속성 컨텍스트를 플러시 하는 방법은 3가지가 있다.
em.flush()
직접 호출
Member member = new Member(200L,"member200");
em.persist(member);
em.flush();
tx.commit();
플러시는
영속 상태의 엔티티가 영속성 컨텍스트에서 분리되는 것이다.
영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.
준영속 상태로 만드는 방법
em.detatch(entity)
: 특정 엔티티만 준영속 상태로 변환 em.clear()
: em 안의 영속성 컨텍스트를 다 지움em.close()
: 영속성 컨텍스트를 닫아버림