실전! 스프링 부트와 JPA 활용1(웹 애플리케이션 개발)

Ch07. 웹 계층 개발 - 변경 감지와 병합(merge)

webmaster 2021. 12. 7. 16:58
728x90

준영속 엔티티?

준영속 엔티티

  • 영속성 콘텍스트가 더는 관리하지 않는 엔티티를 말한다.
  • 여기서는 itemService.saveItem(book) 에서 수정을 시도하는 Book 객체다.
  • Book 객체는 이미 DB 에 한번 저장되어서 식별자가 존재한다.
  • 이렇게 임의로 만들어낸 엔티티도 기존 식별자를 가지고 있으면 준 영속 엔티티로 볼 수 있다.

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

1. 변경 감지 기능 사용

변경감지기능 사용

  • ID 값으로 다시 조회하여 영속성 컨택스트가 관리하는 대상으로 변경한 뒤, 변경하고자 하는 값을 변경하여, DirtyCheck를 통해 영속성 컨택스트가 알아서 값을 변경하도록 해준다.

2. 병합( merge ) 사용

Merge 사용

  • 현업에서 잘 사용하지 않는다(내가 원하지 않는 값이 변경될 위험이 있기 때문)
  • JPA가 위에 했던 동작 방식을 모든 속성에 대하여해 준다..

병합 동작 방식

Merge 동작 방식

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

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

  • 개발자가 속성을 선택해서 넣어주는 것이 아니다.
  • 만약 price가  값을 수정하지 않는 경우 null로 세팅이 되어 값이 변경이 된다.
  • 이러한 이유로 변경 감지 기능을 사용하는 것이 실무에서는 더욱 좋다 

엔티티를 변경할 때는 항상 변경 감지를 사용하세요

메소드를 만들어서 update를 해준다.

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