영속성 컨텍스트(Persistence Context)
- JPA 내부동작의 핵심. 엔티티를 영구적으로 저장하는 환경.
- 엔티티 매니저가 생성될 때 하나 만들어지며, 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리
엔티티의 생명 주기
- 비영속(new/transient)
- 단순히 엔티티 객체를 생성하여 영속성 컨텍스트에는 저장되지 않은 상태
- em.merge() 를 통해 비영속 상태의 엔티티를 영속 상태로 만들 수 있음
- 영속(persisted/managed)
- 엔티티 매니저를 통해 영속성 컨텍스트에 객체를 저장하여 관리되고 있는 상태
- EntityManager.persist(entity) ⇒ 엔티티를 영속화. 엔티티 매니저를 통해 영속성 컨텍스트에 접근해 엔티티를 관리한다.
- 준영속(detached)
- 영속성 컨텍스트를 통해 관리되던 엔티티가 관리하지 않게 된 상태
- 영속성 컨텍스트가 제공하는 기능을 사용 못함(변경감지, 1차캐시 등등..)
- 트랜잭션 커밋 시에도 아무 일도 일어나지 않음
- 1차 캐시부터 쓰기 지연 SQL 저장소까지 해당 엔티티를 관리하기 위한 모든 정보가 제거됨.
- em.detach()를 통해 직접 특정 엔티티를 준영속 상태로 만들 경우
- em.clear() 를 통해 영속성 컨텍스트의 모든 엔티티를 준영속 상태로 만들 경우
- em.close() 를 통해 영속성 컨텍스트를 종료할 경우
- 준영속 상태로 만드는 방법
- em.detach(엔티티) : 특정 엔티티만 준영속화
- em.clear() : 영속성 컨텍스트 내의 모든 엔티티를 준영속화
- em.close() : 영속성 컨텍스트를 종료
- em.merge() 를 통해 준영속 상태의 엔티티를 다시 영속 상태로 만들 수 있음
- 삭제(removed)
- 엔티티가 영속성 컨텍스트와 데이터베이스에서 삭제된 상태
영속성 컨텍스트의 특징
- 식별자가 존재
- 영속성 컨텍스트는 엔티티를 식별자 값(@Id 로 테이블 기본키와 매핑된 값)으로 구분하기 때문에 항상 식별자가 존재
- 플러시(Flush)
- 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화하는 작업
- em.flush() 직접 호출 / 트랜잭션 커밋 시 플러시 자동 호출 / JPQL 쿼리, Criteria 실행 시 플러시 자동 호출
- 플러시 실행 시 동작 과정
- 변경 감지 동작, 영속성 컨텍스트의 모든 엔티티를 스냅샷과 비교해 수정된 엔티티 찾음
- 수정된 엔티티는 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 데이터 베이스에 전송
- 1차 캐시
- 영속성 컨텍스트가 내부에 갖고있는 캐시.
- 영속 상태의 엔티티들이 모두 이 곳에 저장
- 키 : 엔티티의 식별자 / 값 : 엔티티 인스턴스
- 엔티티가 영속 상태에 있을 때, 1차 캐시에 엔티티가 보관되어 엔티티 조회 시 1차 캐시에 엔티티가 존재한다면 db를 통해 조회하지 않고 바로 1차 캐시에서 반환.
- 1차 캐시에 없을 시 db에서 조회 후 1차 캐시에 저장해 두고 다시 조회 요청이 발생했을 시 1차 캐시에서 조회
- 영속 엔티티의 동일성 보장
- 같은 식별자의 엔티티를 여러번 조회 시, 항상 1차 캐시의 같은 엔티티 인스턴스를 반환하기 때문에 같은 인스턴스로 인지
- 동일성 : 실제 인스턴스가 같다는 것을 의미
- 동등성 : 인스턴스가 실제 가지고 있는 값의 동일함을 의미
- 같은 식별자의 엔티티를 여러번 조회 시, 항상 1차 캐시의 같은 엔티티 인스턴스를 반환하기 때문에 같은 인스턴스로 인지
- 트랜잭션을 지원하는 쓰기 지연
- 영속 컨텍스트 내에는 쓰기 지연 SQL 저장소 라는 곳이 존재
- 이곳에 sql을 쌓아두고 트랜잭션을 커밋할 때 한번에 DB에 보냄(flush)
- 변경 감지(Dirty Checking)
- 영속 상태인 엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 기능
- 플러시 시점에 스냅샷과 엔티티를 비교하여 변경된 엔티티를 찾고, 변경이 있을 경우 수정 쿼리를 생성, 변경사항을 데이터베이스에 반영
- 스냅샷 : 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해 두는 것
- 기본적으로는 변경 감지를 통해 수정 쿼리 생성 시, 엔티티의 모든 필드를 업데이트 하는 쿼리를 생성해 재사용 하도록 되어있음. → 하이버네이트의 확장 기능을 통해 동적 쿼리 생성도 가능
- 지연 로딩(Lazy Loading)
- 실제 객체 대신 프록시 객체를 로딩해두고 해당 객체를 실제 사용할 때 영속성 컨텍스트를 통해 데이터를 불러오는 방법
<<자바 ORM 표준 JPA 프로그래밍 - 김영한>> 을 보고 학습한 내용을 바탕으로 정리한 내용입니다.
댓글 피드백은 언제나 환영합니다!
'BackEnd' 카테고리의 다른 글
Nest-cli로 프로젝트 생성 시 git 추적 안되는 문제 (0) | 2024.08.21 |
---|---|
Node.js 의 이벤트 루프 (1) | 2024.03.05 |
DDD - 엔티티와 밸류 (0) | 2024.01.12 |
JPA 빠르게 훑어보기 (0) | 2023.08.20 |
Spring VS SpringBoot (0) | 2020.07.23 |