식별자 값
- 식별자 값은 DB의 기본 키 값과 매핑되어 있다.
- 영속성 컨텍스트는
Entity
를 식별자 값으로 구분한다.
- 따라서 영속 상태의
Entity
는 식별자 값이 무조건 있어야 한다.
- 또한, 영속성 컨텍스트에 데이터를 저장, 조회하는 모든 기준은 DB의 기본 키이다.
영속성 컨텍스트와 DB 저장
- JPA는 트랜젝션을 커밋하는 순간, 영속성 컨텍스트의 entity를 DB에 반영한다.
영속성 컨텍스트의 CRUD
1차 캐시
- 영속성 컨텍스트 내부에 캐시를 갖고 있다.
- 영속 상태의
Entity
는 모두 1차 캐시에 저장된다.
- key를 식별자 값으로 하고, value를
Entity
객체로 한다.
em.find(Member.class, "member1")
으로 조회
- 1차 캐시에
member1
의 식별자 값을 갖는 데이터가 존재할 때

- 1차 캐시에
member1
의 식별자 값을 갖는 데이터가 존재하지 않으면
- DB에서
member1
의 기본 키 값을 갖는 데이터를 조회한다.
- 조회한 데이터로 엔티티 객체를 만든다.
- 1차 캐시에 엔티티 객체를 영속시킨다.
- 영속성 컨텍스트에 영속된 엔티티 객체를 반환한다.
동일성 보장
- 영속성 컨텍스트는 1차 캐시에 있는 값을 반환한다.
- 연속 2번의 조회 시, 반환된 엔티티 객체는 동일한 엔티티 인스턴스이다.
- 따라서, 엔티티의 동일성을 보장한다.
쓰기 지연
tx = em.getTransaction();
tx.begin()
em.persist(A);
em.persist(B);
tx.commit();
persist()
로 엔티티 객체를 영속시키면 1차 캐시에 저장한다.
- SQL 쿼리를 만들어서 내부의 쓰기 지연 쿼리 저장소에 Insert SQL을 모아둔다.
- 트랜젝션의
commit()
이 실행되면, 쿼리 저장소의 쿼리들을 flush
한다.
- 쿼리들을 실행해서, 영속성 컨텍스트와 DB를 동기화한다.(= 같게만든다.)
- 실제 DB에서 트랜젝션 커밋이 완료된다.
JPA가 생성한 쿼리들을 DB에서 커밋하기 전에만 보내면 된다.
따라서, 한 번에 쿼리들을 전달함으로써 성능 최적화가 가능하다.
변경 감지

SQL을 직접 수정하는 경우
- 수정 사항이 발생하는 SQL을 직접 수정해줘야 한다.
- 결국, SQL에 의존적인 개발이 된다.
변경 감지를 사용하는 경우
- 최조 엔티티 객체가 영속될 때의 상태를 복사, 저장해둔다.(
=스냅샷
)
flush
가 일어날 때, 현재 상태와 스냅샷을 비교한다.
- 수정 사항을 SQL로 만들어서 쿼리 저장소에 보낸다.
- 쿼리들이 DB에 반영되고, 트랜젝션이 DB에서 커밋된다.
변경 감지 전략
- 변경 감지는 영속 상태의 엔티티 객체에만 적용된다.
- update 쿼리는 모든 필드를 다룬다. 데이터 전송량이 증가하긴 하지만,
- 모든 필드를 다루면, 항상 update 쿼리가 항상 같아 재사용성이 증가한다.
- DB에 동일한 쿼리를 날리면, DB에서도 캐싱을 이용하여 재사용성이 증가한다.
- 수정된 필드에 대해서만 다루는 것도 어노테이션을 통해서 가능하다.
@DynamicUpdate
엔티티 삭제
Memebr A = em.find(Member.class, "1");
em.remove(A)
remove
가 실행되면, Delete 쿼리가 쿼리 저장소에 등록된다.
- 엔티티 객체 A는 영속성 컨텍스트에서 제거된다.
우연히 들어왔는데 신상이넹ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
공부하고 갑니당 ㅎㅎ