본문 바로가기

Spring boot

[spring boot] 영속성 컨텍스트

영속성 컨텍스트란?

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차 캐시에서 데이터를 가져온다.

출처 : 김영한.(2019).자바 ORM 표준 JPA 프로그래밍 - 기본편(강의자료)


 - em.persist없이 find해 DB에서 데이터 조회할 경우 

      만약 persist없이, 1차 캐시에 없는 데이터를 가져 올 경우 DB에서 데이터를 조회해 1차 캐시에 저장한 후 반환한다.

출처 : 김영한.(2019).자바 ORM 표준 JPA 프로그래밍 - 기본편(강의자료)


 

 - 이미 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차 캐시가 생성됨.