JPA 더티체킹
영속성 컨텍스트의 특징 중 더티체킹(Dirty Checking) 에 대해서 예제를 통해 알아보도록 하겠습니다.
예제를 위해 DB에 MEMBER라는 테이블로 위와 같은 값을 설정하였습니다.
위 데이터를 기준으로 코드를 작성해 보겠습니다.
Main
public class jpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin(); // [트랜잭션] 시작
try {
Member member = em.find(Member.class,1L);
member.setName("Test!!"); // 엔티티만 변경
tx.commit(); // [트랜잭션] 커밋
}catch (Exception e){
}
}
}
코드를 확인해 보면 member의 name값만 변경해 줄 뿐 다른 액션은 하지 않았습니다.
하지만 작동은 어떻게 될까요 ?
코드를 수행해 보면 아래와 같은 로그를 확인 할 수있습니다.
- select 문으로 member를 찾고
- member의 값을 업데이트 하는 쿼리가 실행되는 것을 볼 수 있습니다.
- 실제로 DB값이 업데이트 되는걸 다음과 같이 확인해 볼 수있습니다.
Why ?
어째서 persist나 save와 같이 값을 변경해 준뒤 따로 저장을 해주지 않아도 update가 실행되는 것일까요 ?
이유는 바로 JPA의 영속성 컨텍스트 때문입니다.
위 사진은 트랜잭션 commit 시 동작하는 내부 매커니즘입니다.
- JPA는 엔티티를 조회하면 해당 엔티티의 조회 상태 그대로 영속컨테이너에 스냅샷을 만들어놓습니다. (
find()
) - commit 시 내부적으로 flush 라는 함수가 실행됩니다.
- flush란 ? 영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것을 의미합니다.
- 그리고 트랜잭션이 끝나는 시점에는 이 스냅샷과 비교해서 다른점이 있다면 Update 쿼리를 생성합니다.
- 최종적으로 데이터베이스에 쿼리를 반영하게됩니다.
이러한 동작이 실행되기 위해선 다음과 같은 조건이 충족되어야 합니다.
- 영속 상태(Managed) 안에 있는 엔티티인 경우
- Transaction 안에서 엔티티를 변경하는 경우
결론
Dirty Checking 이란 ?
- 엔티티의 변경이 일어나면, 엔티티의 처음 상태와 비교해 변경 내용을 자동으로 데이터베이스에 반영하는 JPA 특징이다.
감사합니다.
- references:
- https://jojoldu.tistory.com/415
- 자바 orm 표준 jpa 프로그래밍 ( 저자 - 김영한 )
- Written by: 박상길 (fkdl3919@gmail.com)
- reporting date: 2021-05-16