<aside> 💡 참고: 정말 중요한 내용이니 꼭! 완벽하게 이해해야함
</aside>
영속성 컨텍스트가 더는 관리하지 않는 엔티티를 말한다. (여기서는 itemService.saveItem(book) 에서 수정을 시도하는 Book 객체다. Book 객체는 이미 DB 에 한번 저장되어서 식별자가 존재한다. 이렇게 임의로 만들어낸 엔티티도 기존 식별자를 가지고 있으면 준영속 엔티티로 볼 수 있다.)
→ 문제점은 JPA가 관리 안함 ( 영속 엔티티랑 다르게 변경 감지 안일어남 )
@PostMapping("items/{itemId}/edit")
public String updateItem(@PathVariable("itemId") String itemId, @ModelAttribute("form") BookForm form){
// 준영속 상태 객체 (Book 엔터티 객체는 새롭지만 id(식별자)를 set 해줬기에 JPA를 들어갔다 나옴)
Book book = new Book();
book.setId(form.getId());
book.setName(form.getName());
book.setPrice(form.getPrice());
book.setStockQuantity(form.getStockQuantity());
book.setAuthor(form.getAuthor());
book.setIsbn(form.getIsbn());
itemService.saveItem(book);
return "redirect:/items";
}
아래 코드는 변경 감지 기능을 사용했을 때 해당 코드로 변경
(원래는 저 많은 form 파라미터는 DTO 를 통해서 가져감)
@PostMapping("items/{itemId}/edit")
public String updateItem(@PathVariable("itemId") Long itemId, @ModelAttribute("form") BookForm form){
// 준영속 상태 객체 (Book 객체는 새롭지만 id(식별자)를 set 해줬기에 JPA를 들어갔다 나옴)
// Book book = new Book();
// book.setId(form.getId());
// book.setName(form.getName());
// book.setPrice(form.getPrice());
// book.setStockQuantity(form.getStockQuantity());
// book.setAuthor(form.getAuthor());
// book.setIsbn(form.getIsbn());
itemService.updateItem(itemId, form.getName(), form.getPrice(), form.getStockQuantity());
return "redirect:/items";
}
변경 감지 기능 사용
ItemService
// spring의 transactional에 의해서 트랜잭션이 commit이 됨
// -> 커밋이 딱 되면 JPA가 flush라는 것을 날림
// -> 영속성 컨텍스트에 있는 엔티티중에 변경된 애가 뭔지 다 찾음
// -> 찾아서 setter를 통해 바뀐 앤터티에 대해 update쿼리를 DB에 날려서 update 처리함
@Transactional
public void updateItem(Long itemId, String name, int price, int stockQuantity){
Item findItem = itemRepository.findOne(itemId);
// 밑에 처럼 setter막 깔지 말고 이런 의미 있는 메서드 만들어서 사용해라
findItem.change(price, name, stockQuantity);
// findItem.setName(name);
// findItem.setPrice(price);
// findItem.setStockQuantity(stockQuantity);
}
영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법 트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 트랜잭션 커밋 시점에 변경 감지(Dirty Checking) 이 동작해서 데이터베이스에 UPDATE SQL 실행
병합 사용
병합은 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능이다.