@GetMapping("/user/test/update/merge")
@ResponseBody
public User updateUser2() {
// 테스트 회원 "user1" 생성
createTestUser1();
// 회원 "user1" 객체 추가
// 회원 "user1" 을 조회
User user1 = userRepository.findByUsername("user1").orElse(null);
// 회원 "user1" 이 존재하면,
if (user1 != null) {
// 회원의 email 변경
user1.setEmail("updateUser1@sparta.com");
// 회원의 role 변경 (USER -> ADMIN)
user1.setRole(UserRole.ADMIN);
}
// user1 을 저장 -> merge 사용 아래 save코드 참고
userRepository.save(user1);
return user1;
}
jpa의 save 코드
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) { //만약 아이디를 보았을때 기존에 저장되어있는 데이터가 없으면 persist
em.persist(entity);
return entity;
} else {
return em.merge(entity); //기존에 저장되어있는 데이터를 수정
}
}
merge()는 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회한다.
만약 1차 캐시에 엔티티가 없으면 데이터베이스에서 엔티티를 조회하고, 1차 캐시에 저장한다.
조회한 영속 엔티티에 값을 채워 넣어 변경시킨다.
병합은 모든 필드를 교체하기에 merge는 값이 없으면 null로 업데이트 할 위험이 있다.
@GetMapping("/user/test/update/dirtycheck")
@ResponseBody
@Transactional
public void updateUse3() {
// 테스트 회원 "user1" 생성
createTestUser1();
// 회원 "user1" 객체 추가
// 회원 "user1" 을 조회
User user1 = userRepository.findByUsername("user1").orElse(null);
// 회원 "user1" 이 존재하면,
if (user1 != null) {
// 회원의 email 변경
user1.setEmail("updateUser1@sparta.com");
// 회원의 role 변경 (USER -> ADMIN)
user1.setRole(UserRole.ADMIN);
}
}
변경 감지를 이용하면 원하는 속성만 선택해 변경 가능하다. 따라서 변경 감지를 이용해 update하는 것이 적절하다.