JPA

변경 감지(dirty check)와 병합(merge)

쿠카이든 2022. 2. 14. 12:27
728x90
  • (JPA)변경 감지와 병합(merge)
    • 엔티티를 수정하는 2가지 방법으로 변경 감지(dirty checking)와 병합(merge)이 있습니다.
  • 변경 감지 기능 사용
    • 영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법입니다.
    • 트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 트랜잭션 커밋 시점에 변경 감지(Dirty Checking) 이 동작해서 데이터베이스에 UPDATE SQL 실행합니다.
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티

    Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
    findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다.
    
}
  • 병합 사용
    • 준영속 엔티티의 식별자 값으로 영속 엔티티를 조회합니다.
    • 영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체합니다(병합)
    • 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스에 UPDATE SQL이 실행합니다.
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티

    Item mergeItem = em.merge(item);
    
}
  • 주의: 변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만, 병합을 사용하면 모든 속성이 변경됩니다. 따라서, 병합시 값이 없으면 null 로 업데이트 할 위험도 있습니다(병합은 모든 필드를 교체하므로)
  • 최종 권장 코드
    • save() 메서드는 식별자 값이 없으면( null ) 새로운 엔티티로 판단해서 영속화(persist)하고 식별자가 있으면 병합하도록 하며, 전부 null값이 채워지는 오류가 발생하지 않으면서 merge메서드를 활용 가능합니다.
@Repository
public class ItemRepository {

    @PersistenceContext
    EntityManager em;
    
    public void save(Item item) {
        if (item.getId() == null) {
            em.persist(item);
        } else {
            em.merge(item);
        }
    }
}
728x90

'JPA' 카테고리의 다른 글

페치 조인(fetch join) 의 활용  (0) 2022.02.14
회원등록 API v1, v2 차이  (0) 2022.02.14
(Querydsl) ON 절을 활용한 조인  (0) 2022.02.14
queryDsl 기본 조인에 대해  (0) 2022.02.14
Q클래스 인스턴스 사용 방법 두가지  (0) 2022.02.14