- JPA 변경 감지와 플러시2023년 06월 15일
- starryeye
- 작성자
- 2023.06.15.:06
JPA 의 변경 감지와 플러시에 대해 알아보자.
변경 감지
엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 기능을 변경 감지(Dirty Checking) 이라 한다.
플러시
영속성 컨텍스트의 변경 내용을 데이터 베이스에 반영(동기화)한다.
위 그림을 한번 봐주고..
코드를 통해 이해 해보자.
엔티티
Member 를 생성 후, 추가하는 addMember 메서드
findById 를 통해 한번 조회 하고, 닉네임을 변경하고, 다시 조회하는 test 메서드
실행은 다음과 같이 진행 하였다.
test 메서드를 수행하면 내부적으로 어떤 일이 발생하는지 알아보겠다.
1. test 메서드는 하나의 트랜잭션으로 묶여있어서 메서드 내에서는 동일한 영속성 컨텍스트를 이용하게 된다.
2. (29 line) 최초에는 영속성 컨텍스트에 관리 되고 있는 영속 상태의 엔티티가 없기도 하고
1차 캐시에 해당 id(식별자) 로 관리 되는 영속 상태의 엔티티가 없으므로..
데이터 베이스에서 해당 Id 로 조회해서 엔티티를 생성한다.
그리고 1차 캐시에 저장한 후에 영속 상태의 엔티티를 반환한다.
참고>
JPA 는 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해둔다.이것을 스냅샷이라 한다.
결론적으로, 최초 조회 시점에는 조회 결과인 Entity 인스턴스, 최초 상태 복사본인 스냅샷 이 두가지 필드를 값으로 하는 key(PK)가 1차 캐시에 저장된다.
주의사항>
1차 캐시에는 @Id, Entity, 스냅샷 으로 매핑해서 저장하게 되어있는데..
여기서 Entity 는 객체로 개발자가 반환받아 사용하는 엔티티이다.
Java 는 특수 객체를 제외하고 객체 할당이 기본으로 얕은 복사임을 인지하자
(필자는 여기서 무의식 속에 깊은 복사로 생각하여 굉장한 오해를 몇개월간 하고 있었다.)
cache-aside 전략이라 볼 수 있다.
3. (31 line) 반환 받은 엔티티 객체의 nickname 값을 변경하였다.
해당 인스턴스는 1차 캐시가 가지고 있는 엔티티 인스턴스 이므로
1차 캐시 Entity 인스턴스의 nickname 이 변경 되었을 것이다.
4. (33 line) findById 메서드를 통하여 동일한 id(식별자) 로 1차 캐시에 조회를 한다.
이번에는 1차 캐시에 해당 식별자가 존재하기 때문에 Entity 를 그대로 반환 한다.
그래서, 현재 동일한 인스턴스를 가리키는 Member 변수가 3개인 것이다.
(member1, member2, 1차 캐시 내의 인스턴스)
-> 그래서, 영속성 컨텍스트는 엔티티의 식별자로 동일성을 보장해줄 수 있는 것이다.
(스냅샷은 최초 조회시점인 nickname 이 변경되기전 값을 가지고 있는 최초 상태 복사본이다.)
5. 메서드가 종료되고 플러시, 트랜잭션 커밋이 수행된다.
플러시는 다음의 절차를 따른다.
1. 변경 감지(Dirty Check) 가 동작해서 1차 캐시에 존재하는
엔티티와 스냅샷을 비교하여 수정된 엔티티를 찾는다.
2. 수정된 엔티티는 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 등록한다.
3. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송한다.
<참고>
수정 쿼리는 엔티티의 모든 필드를 업데이트하는게 기본 전략이다.
'Spring > DB, Cache 연동' 카테고리의 다른 글
Spring 과 JPA (0) 2024.02.14 JPA 등록, 기본 키 생성 전략 (0) 2023.06.19 JPA Entity Default Constructor (1) 2023.06.07 JPA Merge, Dirty Check (0) 2023.06.06 Spring Cache Annotation (0) 2023.06.04 다음글이전글이전 글이 없습니다.댓글