[JPA] 변경 감지(dirty checking) 와 병합(merge)

Manx·2022년 4월 28일
0

영속성 컨텍스트(persistence context)

  • 엔티티 매니저로 엔티티를 저장하거나 조회하면 영속성 컨텍스트에 엔티티를 보관하고 관리한다.
  • Transaction을 커밋할 때 영속성 컨텍스트에 새로 저장, 수정된 엔티티를 DB에 반영한다. (flush)
  • 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스와 같은 역할

준영속 (detached)

  • 엔티티 매니저가 더이상 관리하지 않는 엔티티를 뜻한다.

데이터의 수정이 일어났을 때, 업데이트된 정보를 DB에 반영하는 두 가지 방법이 있다.

병합(merge) 사용

@PostMapping("items/{itemId}/edit")
public String updateItem(@PathVariable String itemId, @ModelAttribute("form") BookForm form) {

	Book book = new Book();
	book.setId(form.getId());

	itemService.saveItem(book);
	return "redirect:/items";
}


//    public void saveItem(Item item) {
//        if (item.getId() == null) {
//            em.persist(item); // 신규 등록
//        } else {
//            em.merge(item); // 병합
//        }
//    }

변경되어 넘어온 BookForm을 새로운 Book 객체에 Setter를 통해 변수들을 설정하면 자동으로 업데이트 되지 않는다.
그 이유는 book은 단지 내가 만들었을 뿐 영속성 객체가 아니기 때문이다.
이를 업데이트할 수 있는 방법이 바로 merge이다.
merge는 내가 이해한 바로는 영속성 컨텍스트에 등록되어 있는 영속성 엔티티와 내가 생성한 book을 병합시켜주는 것이다.
그러나, 값이 설정되지 않은 것들도 병합되기 때문에 null값이 들어갈 수 있어 실무에서는 절대 사용하면 안 된다.

변경 감지(dirty checking) 기능 사용

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
	Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
	findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다.
}

그렇다면 위의 코드에 findItem도 merge 해줘야 할까?

그럴 필요가 없다. 왜냐하면 em.find로 찾은 엔티티는 영속성 엔티티이기 때문!
자동으로 반영된다.


Reference

profile
백엔드 개발자

0개의 댓글