영속성 컨텍스트는 캐시를 통해 Entity 객체를 효율적으로 관리하고 있다.
first-level cache(1차 캐시)
- 영속성 컨텍스트는 내부적으로 캐시 저장소를 가지고 있다.
- Entity 객체들이 1차 캐시 즉, 캐시 저장소에 저장된다.
- 캐시 저장소는 Map 자료구조 형태
- key에는 @Id로 매핑한 기본 키 즉, 식별자 값 저장
- value에는 해당 Entity 클래스의 객체 저장
- 영속성 컨텍스트는 캐시 저장소 Key에 저장한 식별자값을 사용하여 Entity 객체를 구분하고 관리
ActionQueue(쓰기 지연 저장소)
- JPA는 트랜잭션 처럼 SQL을 모아서 한번에 DB에 반영한다.
- JPA는 이를 구현하기 위해 쓰기 지연 저장소를 만들어 SQL을 모아두고 있다가 트랜잭션 commit 후 한번에 DB에 반영한다.
예시
- em > actionQueue > insertions > executables
- Insert할 memo#2, memo#3 Entity 객체 2개가 들어가 있음
- 트랜잭션 commit 후
- actionQueue에 있던 insertions 데이터가 사라짐
flush()
em.flush();
: 영속성 컨텍스트의 변경 내용들을 DB에 반영하는 역할 수행
- 즉, 쓰기 지연 저장소의 SQL들을 DB에 요청하는 역할 수행
- commit할때 자동으로 호출됨
Dirty Checking(변경 감지)
- 영속성 컨텍스트에 저장된 Entity가 변경될 때마다 Update SQL이 쓰기 지연 저장소에 저장된다면?
- 하나의 Update SQL로 처리할 수 있는 상황을 여러번 Update SQL을 요청하게 되기 때문에 비효율적
- JPA는 영속성 컨텍스트에 Entity를 저장할 때 최초 상태(LoadedState)를 저장
- 트랜잭션이 commit되고
em.flush();
가 호출되면 Entity의 현재 상태(entityInstance)와 저장한 최초 상태(LoadedState)를 비교
- 변경 내용이 있다면 Update SQL을 생성하여 쓰기 지연 저장소에 저장하고 모든 쓰기지연 저장소의 SQL을 DB에 요청
- 마지막으로 DB의 트랜잭션이 commit 되면서 반영
- 따라서 변경하고 싶은 데이터가 있다면, 먼저 데이터를 조회하고 해당 Entity 객체의 데이터를 변경하면 자동으로 Update SQL이 생성되고 DB에 반영됨
- 이러한 과정을 변경 감지, Dirty Checking이라함!