본문 바로가기
강의 정리/자바 ORM 표준 JPA

2. 영속성 관리

by 이석준석이 2020. 12. 26.

1. 엔티티 매니저 팩토리와 엔티티 매니저

DB 하나당 하나의 EntityManager Factory 가 있으며, EntityManager 을 요청마다 생성해 Connection pool 에 있는 커넥션을 사용하여 DB 에 접근하여 데이터를 CRUD 한다.


2. 영속성 컨텍스트

  • 엔터티를 영구 저장하는 환경이라는 뜻이다.
  • 영속성 컨텍스트는 엔터티 매니저를 통해 접근할 수 있다.

 

엔터티의 생명 주기

  • 비영속 (new / transient)
    • 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
    • ex) new Member();
  • 영속 (managed)
    • 영속성 컨텍스트에 관리되는 상태
    • ex) entitymanager.persist(member);
    • ex) entitymanager.find(Member.class, "id")
  • 준영속 (detached)
    • 영속성 컨텍스트에 저장되었다가 분리된 상태
    • ex) entityManager.detach(member);
      • 영속성 컨텍스트에서 다시 지운다.
  • 삭제 (removed)
    • 삭제된 상태 
    • ex) entityManager.remove(member);
      • 데이터베이스에서 지우겠다.

3. 영속성 컨텍스트의 장점

 

3.1. 1차 캐시

1차 캐시 구조

  • Key : @Id
  • Value : Entity 그 자체

em.find (클래스타입, @Id) 동작 원리

  • 데이터베이스에서 먼저 찾는게 아닌, 1차 캐시에 먼저 @Id 에 대한 값이 존재하는지 찾는다.
  • 존재하지 않는다면
    • 데이터베이스에서 조회해서 값을 가져온다, 이후에 1차 캐시에 저장한다.

3.2. 영속된 엔터티의 동일성 보장

Member member1 = em.find(Member.class, 101L);
Member member2 = em.find(Member.class, 101L);

System.out.println(member1 == member2);

위의 코드는 true 를 반환한다.

  • 1차 캐시에 저장된 value 의 같은 엔터티를 꺼내서 확인하기 때문이다.
  • REPEATABLE READ 의 Isolation Level 을 제공한다.

3.3. 트랜잭션을 지원하는 쓰기 지연

 

트랜잭션을 커밋하기 전 까지는 write 쿼리를 데이터베이스에 보내지 않는다.

  • 트랜잭션을 커밋하는 순간, 데이터베이스에 쿼리를 전송한다.
    • em.persist를 할 때마다 쓰기지연 SQL 저장소에 insert query를 저장한다.
    • tx.commit() 을 하는 순간
      • 쓰기 지연 SQL 저장소에 있던 쿼리들이 flush가 되면서 데이터베이스에 반영되고, db.commit();
  • hibernate.jdbc.batch_size 옵션을 이용해서 한번에 쿼리를 보내고 db를 커밋하는 등의 작업을 할 수 있음

3.4. 엔티티 수정 / 변경감지 (dirty check) 기능

Member member = em.find(Member.class, 1L);
member.setName("zzzzz");

// em.persist(member);

 

JPA 는 transaction commit 시점에

  1. 내부적으로 flush() 가 호출된다.
  2. 엔터티와 스냅샷을 비교한다.
    • 스냅샷 : 값을 최초에 읽어온 시점의 값을 복사해 놓은 것
    • 위의 코드는 그러면 엔터티와 스냅샷에 다른 값이 들어있을 것이다.
  3. 스냅샷이 다르면, 쓰기 지연 SQL 저장소에 update SQL을 생성한다.

 


4. 플러시

  • 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것이다.
  • 쓰기지연 저장소에 있는 쿼리를 전송하는 것.

순서

  1. 변경 감지
  2. 수정된 엔터티를 쓰기 지연 SQL 저장소에 등록
  3. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 (등록, 수정, 삭제 쿼리)

플러시가 실행되는 경우

  • em.flush();
  • tx.commit();
  • jpql 쿼리 실행

플러시 모드 옵션 [em.setFlushMode(아래에 있는 옵션)]

  • FlushModeType.AUTO (defualt)
    • 커밋 + JPQL 을 사용하는 경우 플러시
  • FlushModeType.COMMIT
    • 커밋할 때만 플러시

플러시는

  • 1차 캐시가 지워지거나, 영속성 컨텍스트를 비우는 것은 아니다.
  • 영속성 컨텍스트에 변경 내용을 데이터베이스에 동기화하는 것이다.

5. 준영속 상태

  • 영속 상태의 엔터티가 영속성 컨텍스트에서 분리됨 (detached)
  • 영속성 컨텍스트가 제공하는 기능 (변경 감지, update SQL 등) 을 사용하지 못한다.

준영속 상태로 만드는 법

  • em.detach(member) 
    • 특정 엔터티만 준영속 상태로 전환
  • em.clear()
    • 영속성 컨텍스트를 아예 초기화
  • em.close();
    • 영속성 컨텍스트를 아예 닫아버림

'강의 정리 > 자바 ORM 표준 JPA' 카테고리의 다른 글

6. 고급 매핑  (0) 2020.12.29
5. 다양한 연관관계 매핑  (0) 2020.12.28
4. 연관관계 매핑 기초  (0) 2020.12.27
3. 엔티티 매핑  (0) 2020.12.27
1. JPA 시작하기  (0) 2020.12.26