본문 바로가기
ORM/JPA

[JPA] 더티 체킹(dirty checking) 정리

by 젊은오리 2023. 4. 16.
728x90

더티 체킹이란?

JPA에서 더티 체킹(dirty checking)이란 영속성 컨테이너가 관리하는 엔티티의 상태를 감지해서, 변경된 부분이 있다면 자동으로 트랜잭션이 끝나는 시점에 데이터베이스에 반영하는 기능이다. 따라서 여기서 말하는 dirty는 “엔티티 데이터의 변경된 부분”을 뜻하며 dirty checking은 변경된 부분을 감지한다는 의미이다.

따라서 개발자가 update에 관련된 쿼리를 작성하지 않아도 되기 때문에, 코드의 복잡성을 줄일 수 있다는 특징이 있다. 그렇다면 어느 상황에서 더티 체킹이 일어나는 지 알아보자.

 

더티 체킹 조건

  • 영속성 컨텍스트에서 관리되는 엔티티

영속성 컨텍스트는 엔티티를 처음 조회할 때 시작되며, 이후 변경을 감지한다. 준영속/비영속 상태의 엔티티는 더티 체킹의 대상이 되지 못한다.

  • Transaction이 커밋되었을 때

트랜잭션이 커밋되기 전까지 영속성 컨텍스트는 변경사항을 추적하기만 하고, DB에 반영하지는 않는다. 따라서 트랜잭션이 커밋될 때 영속성 컨텍스트는 엔티티의 변경된 상태를 DB에 반영한다.

 

코드 예시

아래 코드는 Service단에서 member의 id를 받아 name을 수정하는 메서드이다. 보다시피 member에서 setName()으로 name을 수정하기만 했을 뿐, save()메서드 등을 통해 저장하는 부분은 구현하지 않았다.

@Transactional
public void update(Long id, String name) {
    Member member = memberRepository.findOne(id);
    member.setName(name);
}

 

Postman으로 API를 실행했을 때, findOne()메서드로 member를 찾은 후, 자동으로 update쿼리를 날리는 모습을 확인할 수 있다.

더티 체킹을 통해 자동으로 생성된 update쿼리는 기본적으로 모든 필드를 업데이트한다. 위에 보다시피 name만을 변경했지만, 실제로 쿼리는 city, street, zipcode, name 모두 업데이트 하는 걸 볼 수 있다.

 

따라서, 변경된 필드만 업데이트 되도록 하고자 하면 다음과 같이 @DynamicUpdate 어노테이션을 붙임으로써 가능하다.

@Entity
@Getter @Setter
@DynamicUpdate //추가
public class Member {

    @Id @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String name;

    @Embedded
    private Address address;

    @JsonIgnore
    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();

 

다시 로그를 확인해보면, name만 업데이트 된 걸 볼 수있다.

728x90

댓글