Framework | Library | Tool/Spring Data | JPA

JPA, 영속성 컨텍스트와 상태 관리

주정용 2021. 9. 5. 22:44
728x90

영속성 컨텍스트란

  • 엔티티를 관리해주는 컨테이너
  • 엔티티는 다양한 상태로 존재함
  • 엔티티의 상태를 기준으로 DB와 애플리케이션 사이에서 캐시의 역할을 수행
  • 컨테이너에서 필요한 정보를 persistence.xml로부터 가져옴
  • entityManager를 생성할 때 자동으로 생성되며, entityManager의 메서드를 통해서만 접근할 수 있음

엔티티의 상태

  • 생성(new)
    • 비영속 상태
    • 엔티티가 컨테이너에 등록되지 않은 상태
    • 엔티티 객체는 컨테이너와 DB와 아무런 관련이 없음
  • 관리(managed)
    • 영속 상태
    • 엔티티가 컨테이너에 등록된 상태
    • persist()에 의한 managed
      • 실제 persist 메서드가 트랜잭션 안에서 이뤄져야 함
      • managed 상태의 엔티티를 수정하면 트랜잭션 종료시점에 update 처리가 이뤄짐(dirty checking)
    • find()에 의한 managed
      • 엔티티가 컨테이너에 존재하면 그대로 반환
      • 엔티티가 컨테이너에 없으면 DB 조회, 엔티티 생성, 컨테이너에 등록
      • 컨테이너에 식별자에 해당하는 객체가 없을 때만 select 처리가 이뤄짐
  • 분리(detached)
    • 준영속 상태
    • 엔티티가 관리 상태에서 컨테이너로부터 분리된 상태
    • 생성 상태는 식별자 값이 없지만, 분리 상태는 식별자 값이 있음
    • merge 메서드를 통해서 엔티티의 상태를 managed로 되돌릴 수 있음
  • 삭제(removed)
    • 엔티티가 컨테이너에서 삭제된 상태
    • 트랜잭션 종료 시점에 DB에서도 해당 데이터가 삭제됨

엔티티 캐시

  • 컨테이너는 flush 요청이 있을 때만 엔티티의 상태 변화를 DB에 동기화함
    • entityManager의 flush() --> 명시적 플러시
    • transaction commit --> 묵시적 플러시
    • JPQL을 이용한 쿼리 --> 쿼리 전송 직전 묵시적 플러시
  • 플러시 모드는 entityManager에서 변경할 수 있음
    • FlushModeType.AUTO가 기본값

트랜잭션 커밋과 플러시

  • 컨테이너는 commit 수행 전 엔티티 캐시의 변경 사항에 대해서 플러시를 선행함
  • 개별적인 SQL 구문들이 모여서 한 번의 DB Connection으로 처리됨

엔티티 수정

  • 엔티티를 수정하려면 엔티티가 엔티티 캐시에 있어야 함

    변경 감지(Dirty Check)

  • 컨테이너가 캐시에 등록된 엔티티 중 수정사항이 있는 엔티티를 찾는 과정
  • dirty check를 통한 update는 모든 컬럼 수정을 원칙으로 함
    • 변경된 사항만 update 처리하려면 엔티티 클래스에서 하이버네이트의 @DynamicUpdate 선언

      merge와 saveOrUpdate

  • entityManager의 merge는 엔티티가 생성 상태라면 insert, 분리 상태라면 update로 작동
    • 상태 판단의 기준은 엔티티 식별자 값의 유무

      엔티티 갱신

  • DB의 변화를 엔티티에 반영하는 기능
  • entityManager의 refresh 메서드를 통해 엔티티 갱신

엔티티 검색

find()

  • 검색 결과가 없을 때 null을 반환
  • 메서드 호출 즉시 SELECT 처리(Eager-loading)

getReference()

  • 검색 결과가 없을 때 throw exception
  • 엔티티가 실제로 사용되는 시점에 SELECT 처리(Lazy-loading)

참고자료

JPA 퀵스타트, 채규태