영속성 컨텍스트의 마지막 남은 특징 변경 감지(Dirty Checking)에 대해 알아보고 영속성 컨텍스트는 이것으로 마무리하고자 한다.
먼저 변경 감지에 대해 알아볼건데, 바로 아래 코드를 보자
(Member 테이블에는 id(PK)가 1이고 name이 "member1"인 데이터가 하나 들어있다고 가정)
🎈 예제 코드 1
Member findMember1 = em.find(Member.class, 1L);
findMember1.setName("member2");
tx.commit();
🎉 로그 1
Hibernate:
select
member0_.id as id1_0_0_,
member0_.name as name2_0_0_
from
Member member0_
where
member0_.id=?
Hibernate:
/* update
hellojpa.Member */ update
Member
set
name=?
where
id=?
먼저 em.find() 를 통해 id가 1인 member 데이터를 조회하였으니 select 쿼리가 나온것은 그리 어렵지 않다. 물론 이 과정에서 데이터는 영속성 컨텍스트, 좀 더 정확히는 1차 캐시에 캐싱되며, 객체의 참조값은 findMember 변수에 담기게 된다. 그 후 setter 메서드를 통해 member 객체의 name값을 변경하고 트랜잭션을 커밋했다.
"어? 뭔가 이상하다. 왜 update문이 실행이 됐지?" 라는 생각이 든다. 나는 findMember 객체의 필드값을 변경했을뿐, DB나 JPA와 관련 된 코드는 작성하지 않았다. 값을 바꿧으니 update()(존재하는지 모르겠지만) 와 같은 코드가 필요한것처럼 보인다.
이런 마법같은일이 가능한 이유는 영속성 컨텍스트의 변경 감지(Dirty Checking) 특성 덕분이다. 아래 그림을 살펴보자
앞서 설명한 1차캐시는 위 그림처럼 스냅샷이라는게 존재하는데 저 스냅샷은 member 객체가 1차캐시에 저장될 때 함께 저장된다. 이후 트랜잭션이 커밋 또는 플러시가 일어나는 시점에 현재 엔티티 객체와 스냅샷을 비교하여 변경사항이 있다면 이에 해당하는 UPDATE문을 만들어 DB에 보내게 된다. JPA에서는 이러한 기능을 변경 감지(Dirty Checking)라고 부른다.
마지막으로 영속성 컨텍스트의 지연 로딩(Lazy Loading)이라는 중요한 특성이 있는데, 이 부분은 member 테이블 하나로만 설명하기엔 좀 부족한감이 있어 이번 영속성 컨텍스트 시리즈에선 설명하지 않고 좀 더 미뤄두고자 한다.
이것으로 영속성 컨텍스트에 대한 설명을 마무리한다. 써놓고 보니 별건 아닌데 너무 주절주절 길게 설명한것 같기도 하고, 회사핑계 무슨핑계 대면서 블로그 글 쓰는 텀이 굉장히 길다. 이젠 퇴사도 하고 핑계거리도 없으니 더 자주 쓰도록 노력하겠다😬