조회한 영속 엔티티 'mergeMember' 에 'member' 엔티티의 값을 채워 넣는다.
member엔티티의 모든 값을 mergeMember에 밀어 넣는다.
이때 mergeMember의 "회원 1"이라는 이름이 "회원명변경"으로 바뀐다.
영속 상태인 mergeMember를 반환한다.
동작 방식을 간단히 정리
준영속 엔티티의 식별자 값으로 영속 엔티티를 조회한다.
영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체한다.(병합한다)
트랜잰셕 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스 UPDATE SQL이 실행된다.
주의! 변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만 , 병합을 사용하면 모든 속성이 변경된다. 병합 시 값이 없으면 null로 업데이트할 위험도 있다. (병합은 모든 필드를 교체한다)
예제로 확인하기 (itemRepository 분석)
package jpabook.jpashop.repository;
@Repository
public class ItemRepository {
@PersistenceContext
EntityManager em;
public void save(Item item) {
if (item.getId() == null) {
// 식별자 값이 없으면 새로운 엔티티로 판단해서 영속화(persist)하고
em.persist(item);
} else {
// 식별자 값이 있으면 병합(merge)
// 준영속 상태인 상품 엔티티를 수정할 때는 id 값이 있으므로 병합 수행
// 주의!
// Item mergeItem = em.merge(item)
// em.merge의 반환을 받은 mergeItem은 영속 상태이고
// 파라미터로 받아온 item은 여전히 준영속 상태이다.
em.merge(item);
}
}
//...
}
신규 데이터를 저장하는 것 뿐만 아니라 변경된 데이터의 저장도 한다.
여기서 사용하는 수정(병합)은 준영속 상태의 엔티티를 수정할 때 사용한다.
핵심
Q.
여기서의 new Book()으로 생성된 "book" 객체는 준영속 엔티티이다.
HTML Form에서 가져온 BookForm form의 데이터를 담은 "book" 객체가 왜 준영속 엔티티일까?
단순히 setId를 해준 것 밖에 없는데?
A.
준영속은 객체를 new 했거나 , 안 했거나를 기준으로 나누는 것은 아니다.
핵심은 식별자(key)를 기준으로 영속상태가 되어 DB에 저장된 적이 있는가로 볼 수 있다.
new 상태인 객체와 준영속 상태의 객체는 merge()라는 명령에서 동작에 차이가 있다.
new 상태인 객체는 merge()를 호출할 때 완전히 새로운 엔티티를 만든다.
반면에 준영속 상태의 엔티티는 DB에서 기존 엔티티를 찾고 그 값을 준영속 상태의 객체로 변경한 후 반환한다.
마치 준영속 상태의 객체가 영속 상태가 된 것 처럼
가장 좋은 해경 발법
엔티티를 변경할 때는 항상 변경 감지를 이용하자
컨트롤러에서 어설프게 엔티티를 생성하지 말자
트랜잭션이 있는 서비스 계층에서 식별자(id)와 변경할 데이터를 명확하게 전달하자
트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회 하고 , 엔티티의 데이터를 직접 변경하자.(원하는 필드만)
변경 감지와 병합 (준영속 엔티티)
준영속 엔티티? ★
준영속 엔티티를 수정하는 2가지 방법
변경 감지 기능 사용
병합(merge) 사용
병합 동작 방식
동작 방식을 간단히 정리
예제로 확인하기 (itemRepository 분석)
핵심
Q.
A.
가장 좋은 해경 발법
엔티티를 변경할 때는 항상 변경 감지를 이용하자
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 - 인프런
실무에 가까운 예제로, 스프링 부트와 JPA를 활용해서 웹 애플리케이션을 설계하고 개발합니다. 이 과정을 통해 스프링 부트와 JPA를 실무에서 어떻게 활용해야 하는지 이해할 수 있습니다. 초급
www.inflearn.com
'기록 > 스프링 부트 와 JPA 활용' 카테고리의 다른 글