DB/JPA

[JPA]변경 감지(Dirty Checking)와 병합(merge)

꾹꾹이 2022. 9. 25.
728x90

준영속 엔티티란?

  • 영속적 컨텍스트가 관리하지 않는 엔티티.
  • DB에 한 번 거친 데이터(식별자가 생성된 상태).
  • 임의로 만들어낸 엔티티도 기존 식별자를 가지고 있으면 준영속 엔티티.

 

준영속 엔티티를 수정하는 방법 2가지

1. 변경감지(Dirty Checking)

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
        Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
        findItem.chagePrice(itemParam.getPrice()); //데이터를 수정한다. 
}
  • 영속성 컨텍스트에서 데이터를 다시 조회한 후에 데이터를 수정하는 방법
  • 파라미터로 넘어온 itemParam은 DB에서 꺼내온 데이터로, 준영속 상태이다. 데이터를 아무리 바꿔치기 하더라도 persist나 merge하지 않는 이상 데이터가 변경되지 않는다.
  • 트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 → 트랜잭션 커밋 시점에 변경 감지(Dirty Checking)이 동작해서 데이터 베이스에 UPDATE SQL 실행

 

2. 병합(merge)

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티 
        Item mergeItem = em.merge(item);
}
  • 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능
  • merge()를 실행한다.
  • 준영속 엔티티의 식별자 값으로 영속 엔티티를 조회한다.
  • 영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체(병합)한다.
  • 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터 베이스에 UPDATE SQL이 실행된다.
  • ❗️주의❗️ 변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만, 병합을 사용하면 모든 속성이 변경된다. 병합 시 값이 없으면 null로 업데이트 될 수 있다.(병합은 모든 필드를 교체)

 

 

 

실무에서는 보통 업데이트 시 변경할 데이터만 노출하기 때문에 병합을 사용하는 것이 매우 번거롭고 가독성을 떨어뜨릴 수 있다.

때문에 변경 감지를 사용하는 것이 좋다.

또한 setter없이 바로 추적할 수 있는 메서드를 만들자(유지보수를 위해)

댓글