영속성 컨텍스트(Persistence Context)
영속성 컨텍스트란 무엇일까
영속성 컨텍스트
영속성 컨텍스트란?
“엔티티를 영구 저장하는 환경”
- 영속성 컨텍스트는 눈에 보이지 않는 논리적인 개념
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근(영속성 컨텍스트 안에 엔티티 매니저 존재)
엔티티의 생명주기
비영속성
Member member = new Member();
member.setId("memeber1");
member.setUsername("회원1");
- 객체를 생성만 해서 영속성 컨텍스트와는 관련이 없는 상태
- 즉 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
영속
Member member = new Member();
member.setId("memeber1");
member.setUsername("회원1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 객체를 생성한 상태(영속)
em.persist(member);
persist
메서드에 memeber 객체를 담아서 영속성 컨텍스트에 전달- 영속성 컨텍스트에 관리되는 상태
준영속, 삭제
Member member = new Member();
member.setId("memeber1");
member.setUsername("회원1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(member);
// 영속성 컨텍스트에서 분리
em.detach(member)
// DB에서 삭제
em.remove(member)
detach
메서드로 member 객체를 영속성 컨텍스트에서 분리-
영속성 컨텍스트에 저장되었다가 분리된 상태
remove
메서드로 member 객체를 DB에서 삭제- 데이터베이스에서 삭제된 상태
영속성 컨텍스트의 장점
1차 캐시
Member member = new Member();
member.setId("memeber1");
member.setUsername("회원1");
// 1차 캐시에 저장됨
em.persist(member);
// 1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
- 객체를 조회하면 먼저 1차 캐시에서 찾아보고 있으면 객체 반환
- 만약 객체가 1차 캐시에 없으면 DB 조회 후 1차 캐시에 저장하고 객체 반환
- 트랜잭션 단위로 캐시가 생성, 삭제되어서 사실 성능에 큰 차이는 없음
영속 엔티티의 동일성 보장
Member member = new Member();
member.setId("memeber1");
member.setUsername("회원1");
// 1차 캐시에 저장됨
em.persist(member);
// 1차 캐시에서 조회
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b); // True
- 1차 캐시로 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 지원
- JPA가 아니라 DB에서 쿼리로 불러왔다면 a != b로 False
트랜잭션을 지원하는 쓰기 지원
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // 트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
// 여기까지 Insert SQL을 데이터베이스로 보내지 않음
// commit 하는 순간 Insert SQL을 데이터베이스로 보냄
transaction.commit();
- 쓰기 지연 SQL 저장소에 INSERT SQL 쿼리 저장
- 엔티티는 1차 캐시에 저장
commit
하는 순간flush
, 즉 모아둔 INSERT 쿼리랑 엔티티 전부 전송(버퍼랑 비슷한 개념)
변경감지(Dirty Checking)
- 따로
update
하지 않아도 영속 컨텍스트 내의 1차 캐시에서 스냅샷(초기 엔티티)과 변경된 엔티티를 비교 후 UPDATE 쿼리 저장 - 이후 한번에 자동으로 데이터베이스로 변경된 엔티티와 UPDATE 쿼리 보내줌