변경 감지와 병합(merge)

컴공생의 코딩 일기·2023년 1월 7일
0

JPA

목록 보기
2/14
post-thumbnail

변경 감지와 병합(merge)

이 글은 김영한님의 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 정리된 글을 제 블로그에 옮긴 글입니다.

준영속 엔티티란?

영속성 컨텍스트가 더 이상 관리하지 않는 엔티티를 말한다. 즉 데이터베이스에 한번 갔다 온 엔티티를 준영속 엔티티라고 한다.

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

  • 변경 감지 기능 사용
  • 병합(merge) 사용

변경 감지 기능 사용

@Transactional
public void updateItem(Long id, String name, int price){
    Item item = repository.findOne(id); // em.find(Item.class, id)
    
    // 데이터 수정
    item.setName(name);
    item.setPrice(price);
}

영속성 컨텍스트에서 엔티티를 조회한 후 테이터를 수정하는 방법

  1. 트랜잭션 안에서 엔티티를 다시 조회
  2. 변경 할 값 선택
  3. 트랜잭션 커밋 시점에 변경 감지 (Dirty Checking) -> 이 동작에서 데이터 베이스에 UPDATE SQL 실행

병합(merge) 사용

병합은 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능이다.

@Transactional
public void update(Item item){
    em.merge(item); // item: 파라미터로 넘어온 준영속 상태의 엔티티
}

병합 동작 방식

  1. merge() 를 실행한다.

  2. 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회한다.

    2-1. 만약 1차 캐시에 엔티티가 없으면 데이터베이스에서 엔티티를 조회하고, 1차 캐시에 저장한다.

  3. 조회한 영속 엔티티(mergeMember)에 member 엔티티의 값을 채워 넣는다. (member 엔티티의 모든 값을 mergeMember에 밀어 넣는다. 이때 mergeMember의 '회원1'이라는 이름이 '회원명변경'으로 바뀐다.)

  4. 영속 상태의 mergeMember를 반환한다.

주의!!!: 변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만, 병합을 사용하면 모든 속성이 변경된다. 병합시 값이 없으면 null로 업데이트 할 위험이 있다. (병합은 모든 필드를 교체)

결론

merge 기능은 모든 필드를 교체한다. 만약 값이 없다면 null 값으로 채워진다. 만약 부분 부분만 업데이트를 진행할 경우 수정하지 않은 부분이 null 값으로 수정될 위험이 매우 크다. 그러므로 merge를 사용하지 말고 변경 감지 기능을 사용하는게 더 바람직하다.

profile
더 좋은 개발자가 되기위한 과정

0개의 댓글