<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";
    }

준영속 엔티티를 수정하는 2가지 방법

변경 감지 기능 사용

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 실행

병합 사용

병합은 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능이다.