더티체킹은 Transaction 안에서 엔티티의 변경이 일어나면, 변경 내용을 자동으로 데이터베이스에 반영하는 JPA 특징이다.
Dirty Checking의 뜻은 변경 감지 정도로 생각할 수 있다. 즉, 변경을 감지해서 DB에 반영한다.
데이터베이스에 변경 데이터를 저장하는 시점
- Transaction Commit
- EntityManager Flush
- JPQL 사용
JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영해준다.
변화의 기준은 최초 조회 상태
JPA에서는 엔티티를 조회하면 해당 엔티티의 조회 상태 그대로 스냅샷을 만든다.
트랜잭션이 끝나는 시점에 스냅샷과 현재의 상태를 비교해 다른점이 있다면 Update Query를 데이터베이스로 전달한다.
더티체킹을 진행하는 검사의 대상
영속성 컨텍스트가 관리하는 엔티티를 대상으로 한다.
- detach 된 엔티티 (준영속)
- DB에 반영되기 전 처음 생성된 엔티티 (비영속)
준영속/비영속 상태의 엔티티는 더티 체킹에 해당사항이 없다.
값을 변경해도 데이터베이스에 반영되지 않음.
@Transactional
public void cancelOrder(Long orderId) {
//주문 엔티티 조회
Order order = orderRepository.findOne(orderId);
//주문 취소
order.cancel();
}
위와 같은 코드의 경우에 update 쿼리에 관한 코드가 전혀 없는데도 불구하고, 실행 시 정상적으로 내용이 update 됨을 확인할 수 있다.
변경 감지는 엔티티 객체 관점에서 보면 원하는 내용만 변경한다.
하지만, 기본적으로 Dirty Checing이 실행하는 SQL은 변경된 엔티티의 모든 내용을 Update Query로 만들어서 전달한다.
전체 필드를 업데이트 하는 방식의 장점?
필드가 많을 겨우 전체 필드 Update 쿼리가 부담스러울 수 있음.
이런 경우에 @DynamicUpdate
어노테이션을 사용하여 변경 필드만 반영되도록 할 수 있다.
아래와 같이 엔티티의 최상단에 @DynamicUpdate
를 선언해주면 된다.
@Getter
@Entity
@NoArgsConstructor
@DynamicUpdate
public class Category {
@Id @GeneratedValue
@Column(name = "category_id")
private Long id;
private String name;