1. 엔티티 매니저 팩토리와 엔티티 매니저
EntityMagagerFactory로부터 각각의 thread마다 EntityManager 인스턴스들을 생성하여 EntityManager가 DB에 접근
2. 영속성 컨텍스트
- "엔티티를 영구 저장하는 환경"이라는 뜻
- 영속성 컨텍스트는 논리적인 개념 -> 눈에 보이지 않음
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근
3. 엔티티의 생명 주기
(1) 비영속(new/transient): 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
(2) 영속(managed): 영속성 컨텍스트에 관리되는 상태
- persist()
- 엔티티가 1차 캐시에 없을 때 find()
(3) 준영속(detached): 영속성 컨텍스트에 저장되었다가 분리된 상태 -> 영속성 컨텍스트가 제공하는 기능을 사용하지 못 함
- detach():특정 엔티티만 준영속 상태로 전환
- clear(): 영속성 컨텍스트를 완전히 초기화
- close(): 영속성 컨텍스트를 종료
(4) 삭제(removed): 삭제된 상태(DB에서도 삭제됨)
4. 영속성 컨텍스트의 이점
(1) 1차 캐시
- 데이터를 조회할 때 DB에 접근하지 않고 1차 캐시에서 조회할 수 있으므로 읽기 성능이 향상
- 데이터가 1차 캐시에 없으면 DB를 조회하여 1차 캐시에 저장함
Member member = new Member();
member.setName("member1");
em.persist(member);
Member findMember = em.find(Member.class, "member1");
(2) 영속 엔티티의 동일성 보장: 1차 캐시로 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 DB가 아닌 애플리케이션 차원에서 제공
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member2");
System.out.println(a == b);
(3) 변경 감지(Dirty Checking)
- 트랜잭션 commit() 명령어가 실행되면 현재 DB 상태와 1차 캐시의 스냅샷을 비교
- 다르면 sql query를 생성하여 flush할 때 추가하여 최종 commit
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member member = em.find(Member.class, "memberA");
member.setName("memberB");
tx.commit()
(4) 지연 로딩(Lazy Loading)
5. 플러시(flush)
영속성 컨텍스트의 변경 내용을 DB에 반영하는 것
(1) 플러시 과정
- 플러시 명령이 발생하면 변경 감지 동작
- 수정된 엔티티를 파악하여 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소 저장소의 쿼리를 DB에 전송
(2) 영속성 컨텍스트를 플러시 하는 방법
- em.flush(): 직접 호출하여 commit() 전에 강제로 플러시
- 트랜잭션 커밋: 플러시 자동 호출
- JPQL 쿼리 실행: 플러시 자동 호출
(3) 플러시의 특징
- 영속성 컨텍스트를 비우지 않음
- 영속성 컨텍스트의 변경 내용을 DB에 동기화
- 트랜잭션이라는 작업 단위 내에서 커밋 직전에만 동기화 하면 됨
참고: 인프런 자바 ORM 표준 JPA 프로그래밍 기본편 - 김영한