영속성 컨텍스트의 이점
- 1차 캐시
- 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
- 변경 감지(Dirty Checking)
- 지연 로딩(Lazy Loading)
1차 캐시
- 영속성 컨텍스트의 1차 캐시
- 조회시 1차 캐시에서 조회를 함
- DB 조회 후 "1차 캐시에 저장 후" 반환
- 다만, EntityManager 를 트랜잭션 단위로 만들고 종료시키므로, 요청 1개에 대해 사용되고 없어짐.
- EntityManager 와 함께 없어지므로 큰 영향은 없음
- 영속성 컨텍스트의 1차 캐시에 있는 객체를 다시 find 하면, 1차캐시 객체 그대로 돌려줌 (쿼리 발생 X)
동일성 보장
- 영속 엔티티의 동일성 보장
- find 한 객체의 == 비교를 해도 true 가 됨
- DB가 아닌 애플리케이션 차원에서 제공
트랜잭션을 지원하는 쓰기 지연
em.persist(memberA);
em.persist(memberB); // 이땐 INSERT SQL 발생 X
transaction.commt(); // 이때 INSERT SQL 을 보냄
-
persist 호출시, 쓰기 지연 SQL 저장소에 INSERT 쿼리를 저장
- transaction.commit() 호출시, 쓰기 지연 SQL 저장소에 쌓인 SQL 이 flush 되고 commit됨
-
JPA 는 reflection 이 일어나기 때문에, default 생성자가 꼭 필요함
변경 감지
- 엔티티 수정 변경 감지 (dirty check)
- 객체 변경 시 자동으로 감지하여 UPDATE 됨
- ※ persist 할 필요가 없음!!!
- JPA commit 호출하면
- flush 가 호출되고, 1차 캐시 내의 entity 와 스냅샷을 비교함
- 스냅샷 : 최초에 영속성 컨텍스트에 들어왔을 때 객체 정보
- 비교해서 데이터가 변경되었다?
- -> UPDATE SQL 생성
- -> 쓰기 지연 SQL 저장소에 저장
- 쓰기 지연 SQL 장소 flush, commit 하여 DB에 반영
flush
- flush
- 영속성 컨텍스트의 변경 내용을 DB에 반영
변경 감지 (dirty check)
- 수정된 엔티티에 대해 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송
영속성 컨텍스트를 플러시 하는 방법
- em.flush() 직접 호출
- 트랜잭션 커밋
- JPQL 쿼리 호출
flush 해도 1차 캐시 유지됨
- 쓰기지연저장소에 쌓인 SQL이 DB에 반영되는 과정
JPQL 쿼리 실행시 flush 가 자동 호출되는 이유
- persist 만 하면 DB에 저장이 안되어있는데, 그 상태에서 JPQL 로 조회한다
- -> flush 안하면 DB에 저장 안되어있으면 조회가 안되니까 문제가 됨
- 그러므로 flush 한다.
flush 옵션
- FlushModeType.AUTO
- FlushModeType.COMMIT
- 커밋할 때만 플러시 (쿼리를 실행할 때에는 커밋을 하지 않는 옵션)
flush는 영속성 컨텍스트를 비우는 것이 아니다
- 변경 내용을 DB에 동기화하는 것.
- 트랜잭션이라는 작업 단위가 중요하므로, 커밋 직전에만 동기화하면 됨
준영속 상태
준영속 상태 (detached)
em.detach(member); //특정 객체만
em.clear(); //영속성 컨텍스트 초기화 -> 1차 캐시 통으로 날림 -> 다 준영속 됨
em.close(); //영속성 컨텍스트 자체가 종료
reference