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이라는 작업 단위가 중요하다!
- flush하는 방법?
- 지연 로딩 (실무에서 중요한 기능이다.)
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 |