[JPA 활용 1] 변경 감지와 병합(merge) 📚

홍정완·2022년 4월 28일
0

JPA

목록 보기
7/38
post-thumbnail
post-custom-banner

변경 감지와 병합(merge) 📚




준영속 엔티티


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

  • 이미 DB에 한번 저장되어 식별자가 존재하는 경우

    • 임의로 만들어낸 엔티티도 기존 식별자를 가지고 있으면 준영속 엔티티



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


  • 변경 감지 기능 사용

  • 병합(merge) 사용




변경 감지 기능 사용 ✅


@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티

 	Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티 조회
	
    findItem.setPrice(itemParam.getPrice()); //데이터 수정
 
}

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


  • 트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 ➡

  • 트랜잭션 커밋 시점에 변경 감지(Dirty Checking) 기능이 동작해서 데이터베이스에 UPDATE SQL 실행




병합 사용 ✅


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

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티

	Item mergeItem = em.merge(item);
    
}

병합 동작 방식



  1. merge() 실행

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

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

  1. 조회한 영속 엔티티(mergeMember)에 member 엔티티의 값을 채워 넣는다.

    • (member 엔티티의 모든 값을 mergeMember에 밀어 넣는다.)

    • (이때 mergeMember의 “회원1”이라는 이름이 “회원명변경”으로 바뀐다.)


  1. 영속 상태인 mergeMember를 반환



❗ 변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만, 병합을 사용하면 모든 속성이 변경된다.


❗❗ 병합 시 값이 없으면 null로 업데이트할 위험도 있다.

  • (병합은 모든 필드를 교체)



결론


  • 엔티티를 변경할 때는 항상 변경 감지를 사용하자

    • 컨트롤러에서 어설프게 엔티티를 생성하지 말자.
    • 트랜잭션이 있는 서비스 계층에 식별자(id)와 변경할 데이터를 명확하게 전달하자. (파라미터 or DTO)
    • 트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회하고, 엔티티의 데이터를 직접 변경하자.
    • 트랜잭션 커밋 시점에 변경 감지가 실행된다.

profile
습관이 전부다.
post-custom-banner

0개의 댓글