[JPA] 스터디 1주차 - 3장 영속성 관리

JPA 스터디 : 3장 영속성 관리

1주차 영속성 관리와 엔티티 매핑

  • 3장 영속성 관리 : 90p-119p
  • 4장 엔티티 매핑 : 122p-153p
  • 5장 연관관계 매핑 기초 : 164p-195p

3장. 영속성 관리

  • 엔티티 매니저는 엔티티를 저장, 수정, 삭제, 조회하는 등 엔티티와 관련된 모든 일 처리

3.1 엔티티 매니저 팩토리 & 엔티티 매니저

DB 하나만 사용하는 애플리케이션 => 일반적으로 EntityManagerFactory 하나 생성

// entity manager factory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");

// entity manager 생성
EntityManager em = emf.createEntityManager();

엔티티 매니저 팩토리

  • 여러 스레드가 동시에 접근해도 안전 : 서로 다른 스레드 간 공유 가능
  • cf) 엔티티 매니저 : 여러 스레드 동시 접근 시 문제 발생 ~> 스레드 간 절대 공유 ❌
  • Connection Pool : Hibernate 등 JPA 구현체들은 EntityMangerFactory 생성할 때 같이 생성

엔티티 매니저

  • 엔티티 매니저 팩토리 통해 생성
  • 동시성 문제 O : 스레드 간 공유 X
  • 데이터베이스 연결이 꼭 필요한 시점까지 커넥션 획득 X
    • eg) 트랜잭션 시작 시 커넥션 획득

3.2 영속성 컨텍스트?

엔티티를 영구 저장하는 환경

  • 엔티티 매니저를 생성할 때 하나 생성됨

3.3 엔티티의 생명주기

entity-lifecycle

  • 비영속(new/transient) : 영속성 컨텍스트와 무관 상태
  • 영속(managed) : 영속성 컨텍스트에 저장된 상태
  • 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제(removed) : 삭제 상태

비영속

  • 엔티티 객체 생성 ~~ 영속성 컨텍스트, 데이터베이스와 무관

영속

  • 엔티티 매니저 통해 엔티티를 영속성 컨텍스트에 저장
  • 영속성 컨텍스트가 관리하는 엔티티 상태
  • em.persist(member) : 엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장
  • em.find() , JPQL 사용해 조회한 엔티티

준영속

  • 영속 상태 엔티티를 영속성 컨텍스트가 관리 하지 않는 상태
  • em.detach(), em.close(), em.clear()

삭제

  • 영속성 컨텍스트, 데이터베이스에서 삭제
  • em.remove(member)

3.4 영속성 컨텍스트 특징

식별자 값

  • 영속성 컨텍스트는 엔티티를 식별자 값(@Id)으로 구분
  • 영속 상태는 식별자 값이 반드시 있어야 함
    • 없을 경우, 예외 발생

DB 저장

  • 영속성 컨텍스트에서 관리하는 엔티티는 플러시하는 순간 DB에 저장됨

장점

  • 1차 캐시
  • 동일성 보장
  • 트랜잭션을 지원하는 쓰기 지연
  • 변경 감지
  • 지연 로딩

엔티티 조회

  • 1차 캐시 : 영속성 컨텍스트가 내부에 가지고 있는 캐시
  • 먼저 1차 캐시에서 조회 -> 없을 경우 DB에서 조회 -> 1차 캐시에 저장, 영속 상태 엔티티 반환
  • 영속성 컨텍스트는 1차 캐시에 있는 같은 엔티티 인스턴스를 반환 : 영속 엔티티의 동일성 보장
  • 1차 캐시를 통해 REPEATABLE READ 등급의 트랜잭션 격리 수준을 DB가 아닌 애플리케이션 수준에서 제공

엔티티 등록

  • 트랜잭션을 커밋할 때 모아둔 쿼리를 DB에 보내는데 이것을 트랜잭션을 지원하는 쓰기 지연

엔티티 수정

  • 변경 감지(dirty checking)
    • 엔티티의 변경사항을 데이터 베이스에 자동으로 반영하는 기능
    • 엔티티가 영속성 컨텍스트에 저장될 때 최초의 상태 : 스냅샷
    • flush 할 때 스냅샷과 엔티티를 비교 -> 변경 시 update 구문 쓰기 지연 sql 저장소에 보냄
    • 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용됨
  • JPA의 기본 전략 : 엔티티의 모든 필드 업데이트
    • 단점 : 데이터 전송량 증가
    • 장점
      • 모든 필드 수정 시 수정 쿼리 미리 생성 후 재사용 가능
      • DB에서도 한 번 파싱된 쿼리 재사용 가능
    • @org.hibernate.annotations.DynamicUpdate 통해 동적 Update SQL 생성 전략 선택 가능
      • 상황마다 다르나 컬럼이 대략 30개 이상 되면 정적 수정 쿼리보다 동적 수정 쿼리가 빠르다고 함 —> 단, 테스트 해봐야!

엔티티 삭제

  • em.remove(member) : 호출하는 순간 영속성 컨텍스트에서 삭제됨

3.5 플러시

영속성 컨텍스트의 변경 내용을 DB에 반영

  1. 변경 감지 동작 -> 영속성 컨텍스트에 있는 모든 엔티티를 스냅샷과 비교. 수정된 엔티티 찾음 -> 수정된 엔티티의 수정 쿼리 생성. 쓰기 지연 SQL 저장소에 등록
  2. 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송

플러시 방법 3가지

  1. em.flush() 직접 호출
  2. 트랜잭션 커밋 시 플러시 자동 호출
  3. JPQL 쿼리 실행 시 플러시 자동 호출
    • JPQL, Criteria 등의 객체지향 쿼리 호출 시
    • JPQL은 sql로 변환되어 DB에서 엔티티 조회. 쿼리 실행 전에 영속성 컨텍스트의 변경 내용을 DB에 반영해야 함.

플러시 모드 옵션

  • javax.persistence.FlushModeType
  • FlushModeType.AUTO : 커밋이나 쿼리 실행 시 플러시 (기본 설정)
  • FlushModeType.COMMIT : 커밋할 때만 플러시

3.6 준영속

엔티티가 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태

  • 준영속 상태의 엔티티는 영속성 컨텍스트 제공 기능 사용 불가
  • 준영속 상태 만드는 법 3가지
    1. em.detach(entity) : 특정 엔티티만 준영속 상태 전환
    2. em.clear() : 영속성 컨텍스트 초기화
    3. em.close() : 영속성 컨텍스트 종료

준영속 상태 특징

  • 거의 비영속 상태에 가까움
  • 식별자 값 소유
  • 지연 로딩 불가

참조

  • 자바 ORM 표준 JPA 프로그래밍, 김영한 지음