실제 JPA가 내부에서 어떻게 동작하는지 이해할 수 있다.
• JPA를 이해하는데 가장 중요한 용어
• “엔티티를 영구 저장하는 환경”이라는 뜻
• EntityManager.persist(entity)
persist() 메서드는 DB에 저장한다는게 아니라 영속성 컨텍스트 라는 곳에 저장하는 것.
EntityMangerFactory는 고객의 요청이 올때마다 EntityManger를 생성한다.
EntityManger는 내부적으로 커넥션 풀을 사용해서 DB를 사용하게된다.
Member findMember = em.find(Member.class, "member1");
Member findMember2 = em.find(Member.class, "member2");
무조건 DB에서 찾는게 아니라 우선적으로 1차 캐시에서 'member1'를 찾는다. 있으면 캐시에 있는 값을 조회해서 주고 없으면 DB에서 조회해서 1차 캐시에 저장하고 그리고 반환해서 준다.
트랜잭션 안에서만 이루어지는 1차 캐시는 큰 성능의 이점은 없다. 찰나에 순간이기 때문에.
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b); //동일성 비교 true
1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을
데이터베이스가 아닌 애플리케이션 차원에서 제공
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋
JPA는 쭉 쌓아놓다가 commit하는 순간에 SQL을 날린다.
JPA의 목적은 Java의 Collection을 다루듯이 다룰수 있게 하는 것이다.
예를 들어 List 에서 객체를 꺼내서 데이터를 변경했다면, 변경된 객체를 다시 컬렉션에 넣지 않는 것 처럼 말이다.
commit 하는 시점에 flush()를 실행된다.
스냅샷 - 값을 딱 읽어온 최초 시점의 객체 상태를 저장해둔다.
• 변경 감지
• 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
• 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 (등록, 수정, 삭제 쿼리)
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();
• 영속 -> 준영속
• 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)
• 영속성 컨텍스트가 제공하는 기능을 사용 못함
• em.detach(entity)
특정 엔티티만 준영속 상태로 전환
• em.clear()
영속성 컨텍스트를 완전히 초기화
• em.close()
영속성 컨텍스트를 종료