본문 바로가기

정보/Database

JPA Persistence Context 는 Git과 흡사하다

1. Persistence Context

JPA에서 영속성 컨텍스트란, JPA에서 엔티티를 관리하는 일종의 캐시, 버퍼(저장소)이다.

DB와의 직접 상호작용을 지연하고, 변경된 엔티티를 관리하다가 한 번에 반영하는 식으로 사용된다.

엔티티를 영구 저장하는 환경이다.

 

EntityManagerFactory는 App의 시작에 EntityManager를 생성하고,

EntityManager가 Persistence Context에 접근하게 해주는 역할을 한다.

 

EntityManager와 Persistence Context는 N:1의 환경.

 

참고. Entity 객체는 NoArgsConstructor의 기본 생성자가 필요하다. reflection API의 사용 때문.

 

 

2. Entity의 생명 주기

  • 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
  • 영속 (managed) : 영속성 컨텍스트에 관리되는 상태
  • 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
    • detached된 것
    • em.detach(단일 entity 준영속화), clear(영속성 컨텍스트 완전 초기화), close(영속성 컨텍스트 종료)
  • 삭제 (removed) : 삭제된 상태
"DB에 쿼리를 보내는 순간은 Persistence Context에 등록된 순간이 아니다.
transaction이 commit 된 순간이다."

 

 

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

  • 1차 캐시
    • Transaction 내에서만 사용하는 캐시
    • 딱히 성능상의 엄청나게 큰 이점은 아니다
    • 참고로 App 전체에서 사용하는 캐시는 2차 캐시
  • 동일성 보장 (1차 캐시를 통한 동일성 비교)
    • 1차 캐시로 REPEATABLE READ 등급의 트랜잭션 격리 수준을 DB가 아닌 App차원에서 제공
  • 트랜잭션을 지원하는 쓰기 지연
    • persist에 entity를 넣을 경우, 1차 캐시에는 entity data를 집어 넣고
    • 쓰기 지연 SQL 저장소에 INSERT SQL을 적재
    • 이 과정이 transaction commit 하기 전까지 계속 진행된다.
    • buffering을 모아서 write하는게 됨 (persistence의 property에 batch_size로 쿼리 batch 개수 설정 가능)
  • 변경 감지 : Dirty Checking
    • 찾아온 데이터를 변경한게 persistence context에 있을 경우, 변경을 감지하고 알아서 업데이트
    • entity와 entity에 대한 snapshot을 가지고 있어서 변경 시 쓰기 지연 SQL 저장소에 SQL이 업데이트
    • 이를 flush라 한다.
      • flush하는 방법?
        em.flush() - 직접 호출
        트랜잭션 커밋 - 플러시 자동 호출
        JPQL 쿼리 실행 - 그 순간 플러시 자동 호출
      • flush 모드 옵션이 있다. em.setFlushMode(FlushModeType.AUTO or COMMIT)
      • 영속성 컨택스트를 비우지는 않는다. DB에 동기화하는 것.
      • 가장 중요한건 Transaction이라는 작업 단위가 중요하다!
  • 지연 로딩 (실무에서 중요한 기능이다.)

 

 

4. Git의 Staging, tracking, commit과 매우 유사하다.

 

git의 staging area라고 생각하면 필자의 생각과 유사한 생각을 할 수 있을 것이다.

Persistence Context와 유사하다고 생각되는 Git의 성질들을 정리해 보았다.

  • staging 하기 전에는 변경 사항을 tracking 하지 않음.
  • staging 한 뒤에는 변경 사항에 대한 tracking
  • 변경 사항을 위한 snapshot을 가지고 있다.
  • commit이 되어야만 git이 추가됨
  • unstaging 기능은 준영속과 유사하다.
  • rollback은 git reset과 흡사하다.

다른 점은 아래와 같다.

  • Git 은 버전 관리를 위해 프로젝트 전체를 관리하고, tracking하지만 JPA는 원하는 Entity에 관심
  • Transaction을 통한 계층화 commit은 존재하지 않음. Git은 계층화라기 보다는 다른 버전을 위한 branch가 있다.
  • 보통 Git은 단방향 소통이 진행된다. JPA처럼 sql을 통해 특정 Entity들을 받아 온 뒤에 update하는 방식이 아님.

표로 정리하면 아래와 같다.

구분 JPA Persistence Context Git 
공통점
변경 사항 추적 Entity가 영속상태가 되면 자동으로 변경사항 추적 git add 로 Staging Area에 추가된 파일을 추적
Snapshot Persistence Context에서 Entity의 초기 상태를 snapshot으로 저장 커밋 시 파일의 스냅 샷을 저장
변경 사항 커밋 Transaction 커밋 시, 변경된 엔티티를 DB에 반영 git commit 시 Staging된 파일을 Git 저장소에 반영
변경 사항 취소, 백업, 복원 트랜잭션 롤백으로 변경사항을 취소 git reset, git revert 등으로 변경 사항 취소
즉시 반영 여부 영속성 컨텍스트에서는 즉시 반영되지 않음
(지연 반영)
Staging 된 변경 사항은 즉시 저장소에 반영되지 않음 (커밋 필요)
준영속 상태 detach git reset으로 staging area에서 빼낼 수 있어 유사하다.
차이점
추적 방식 특정 엔티티만을 추적(Entity 단위) 파일 단위로 전체 프로젝트의 파일 시스템을 추적
계층화된 commit 트랜잭션 단위로 commit 브랜치와 커밋을 통해 버전을 관리
단방향 vs 양방향 소통 DB와 양방향 소통 주로 단방향 소통

 

 

'정보 > Database' 카테고리의 다른 글

연관 관계 Mapping (3)  (0) 2024.11.17
연관 관계 Mapping (2)  (1) 2024.11.15
연관 관계 Mapping (1)  (0) 2024.11.15
Entity Mapping  (3) 2024.11.15
JPA : Java ORM 표준  (2) 2024.11.13