Spring/SpringBoot_JPA

변경 감지와 병합(merge)

민철킹 2021. 5. 24. 21:29

준영속 엔티티

영속성 컨텍스트가 더는 관리하는 않는 엔티티를 의미한다.
DB에 한번 저장되어 식별자가 존재하는 엔티티.
persist() 메서드를 통해 영속성 컨텍스트에 담겼을 때는 식별자가 존재되고, 객체만 생성되었을 때는 식별자가 존재하지 않는다. 따라서 식별자가 존재한다면 준영속 엔티티로 볼 수 있다.

준영속 엔티티를 수정하는 2가지 방법
1. 변경 감지 기능 == dirty checking
2. 병합 사용 == merge

JPA가 관리하는 영속 엔티티는 변경 감지를 통해 어떤 것이 변경되었는지 JPA가 알고 있기 때문에

트랜잭션 COMMIT 시점에 바뀐 부분을 자동으로 UPDATE SQL문을 날려 바꿔준다.


변경 감지 기능 사용

  • Id를 기반으로 영속성 컨텍스트안의 영속성 엔티티를 가져온다.
  • 이것을 파라미터로 넘어온 정보로 수정한다.(실제는 setter 사용 x, 별도의 메서드 사용해야함)
  • 현재 findItem은 영속성 엔티티이므로, 따로 저장해주지 않아도 변경 감지 기능을 통해 JPA가 UPDATE문을 날려준다.
  • @Transactional을 통해 DB에 commit이 되고, JPA가 flush()를 통해 변경을 감지하여 UPDATE

 

 

 

 

병합(merge) 사용

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

  • merge()를 실행
  • 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회
    • 만약 1차 캐시에 엔티티가 없으면 데이터베이스에서 엔티티를 조회하고, 1차 캐시에 저장
  • 조회한 영속 엔티티에 준영속 엔티티의 값을 채움
  • 영속 상태인 엔티티를 반환
  • 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스에 UPDATE SQL이 실행

 

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

 

 


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

 

트랜잭션이 있는 서비스 계층에 식별자( id )와 변경할 데이터를 명확하게 전달(파라미터 or dto)
트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회하고, 엔티티의 데이터를 직접 변경
트랜잭션 커밋 시점에 변경 감지가 실행

 

반응형

'Spring > SpringBoot_JPA' 카테고리의 다른 글

API 개발 고급  (0) 2021.05.27
API 개발 기본  (0) 2021.05.26
테스트 예외처리  (0) 2021.05.20
엔티티 설계 주의점  (0) 2021.05.18
도메인 모델, 테이블 설계  (0) 2021.05.17