영속성 컨텍스트란?
application과 DB사이에 논리적으로 존재하며, 엔티티를 영구 저장하는 환경을 뜻함.
- EntityManager.persist(entity);
- entity를 영속성 컨텍스트에 저장한다.
- EntityManager 속에 있는 영속성 컨텍스트를 통해 entity가 관리된다.
- 쓰기 지연 SQL 저장소에 SQL을 쌓는다.
이점
- 1차 캐시
- 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
- 변경 감지(Dirty Checking)
- 지연 로딩(Lazy Loading)
엔티티의 생명주기
비영속
영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
//객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1")
영속
영속성 컨텍스트에 관리되는 상태
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
//객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername(“회원1”);
//객체를 저장한 상태(영속)
em.persist(member); 또는 em.find(Member.class, member1);
준영속
영속성 컨텍스트에 저장되었다가 분리된 상태
//회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);
삭제
삭제된 상태
//객체를 삭제한 상태(삭제)
em.remove(member);
영속적 컨텍스트의 이점
1. 1차 캐시 (동일한 트랜잭션 내에서만 해당)
- em.persist로 1차 캐시에 데이터 저장하고 find할 경우
em.persist(member)를 하면 데이터는 1차 캐시에 저장된다. 그 후 find를 할 경우 1차 캐시에서 데이터를 가져온다.
- em.persist없이 find해 DB에서 데이터 조회할 경우
만약 persist없이, 1차 캐시에 없는 데이터를 가져 올 경우 DB에서 데이터를 조회해 1차 캐시에 저장한 후 반환한다.
- 이미 find한 데이터 다시 find
findMember1에서 select 쿼리 날리고 findMember2는 1차 캐시에서 데이터 들고 온다.
Member findMember1 =em.find(Member.class, 101L);
Member findMember2 =em.find(Member.class, 101L);
정리 =>
persist를 하면 JPA는 데이터를 영속성 컨텍스트의 1차 캐시에 저장함. find는 1차 캐시에서 먼저 데이터를 찾고, 데이터가 없을 시 DB에서 찾아 1차 캐시에 저장 후 반환.
2. 동일성(identity) 보장
Member a = em.find(Member.class, "member1);
Member b = em.find(Member.class, "member1);
System.out.println(a==b); //true
같은 트랜잭션 내에서 같은 객체를 조회했을때 동일성비교 하면 true가 나온다. (b는 1차 캐시에서 들고오며 a와 같은 데이터이다.)
3. 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin();
Member a = new Member(150L, "member1");
Member b = new Member(160L, "member2");
tx.commit();
(batch 최적화) before : commit시 insert sql쿼리 2개 날라감.(connection 2번)
(batch 최적화) after: sql쿼리 한방에 날라감. (connection 1번)
batch 최적화 : 버퍼에 batch 사이즈만큼 SQL을 모아 DB에 한방에 network 타고 쿼리 보냄.
batch를 사용하기 위해?
//persistence.xml
<property name="hibernate.jdbc.batch_size" value="10"/>
4. 변경 감지(Dirty Checking)
변경 감지 (+merge) 정리 : https://baeji-develop.tistory.com/27
5. 지연 로딩(Lazy Loading)
---뒷 시간에---
em.persist(entity); => 1차 캐시에 저장. 쓰기 지연 SQL 저장소에 SQL 쌓임
em.commit(); => 쓰기 지연 SQL저장소 속 SQL이 실제 DB에 flush되고 commit됨
추가 정보
엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
jpa는 생성자 만들 때 기본 생성자도 있어야함.
고객이 10명이 동시에 접근하면 10개의 별도 1차 캐시가 생성됨.
'Spring boot' 카테고리의 다른 글
[spring boot] 1차 정리(jpa 시작, 영속성관리, 엔티티 매핑) (0) | 2021.10.28 |
---|---|
[spring boot] flush란? persist, flush, commit 비교 (0) | 2021.10.11 |
[Spring boot] H2 DB 연결 & JPA 실행 & 기타 설정, JPQL이란? (0) | 2021.10.09 |
[spring boot] 정적 컨텐츠, MVC와 템플릿 엔진, API (0) | 2021.09.16 |
[spring boot] 프로젝트 생성 및 실행, 빌드 (0) | 2021.09.16 |