변경 감지와 병합(merge)

유병익·2022년 11월 29일
0
post-thumbnail

1. 준영속 Entity


정의

  • 영속성 컨텍스트가 더는 관리하지 않는 Entity

2. 준영속 Entity의 수정


  • 준영속 Entity를 수정하는 방법
    • 변경 감지 기능
    • 병합(merge) 사용

2.1 변경 감지


How?

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



2.2 병합(merger)


How?

  • 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
		Item mergeItem = em.merge(item);
}



2.2.1 병합 동작 방식


  1. merge() 실행
  2. 파라미터로 넘어온 준영속 엔티티의 식별자로 1차 캐시에서 엔티티 조회
    • 1차 캐시에 없으면 데이터베이스에서 엔티티를 조회하고, 1차 캐시에 저장
  3. 조회한 엔티티(영속 상태)에 member 엔티티의 값을 채워 넣는다.
    • member 엔티티의 모든 값 을 mergeMember에 밀어 넣는다.
    • 이때 mergeMember의 “회원1”이라는 이름이 “회원명변경”으로 변경
  4. 영속 상태인 mergeMember를 반환

⚠️ 주의

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



3. 정리


  • Entity의 수정은 항상 변경 감지를 사용
  • Controller에서 어설프게 Entity 생성 X
  • 트랜잭션이 있는 서비스 계층에 식별자(id)와 변경할 데이터를 명확하게 전달
    • 파라미터 or DTO
  • 트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회 & 엔티티의 데이터를 직접 변경
    • 트랜잭션 커밋 시점에 변경 감지 실행
profile
Backend 개발자가 되고 싶은

0개의 댓글