: 영속성 컨텍스트가 더는 관리하지 않는 엔티티를 뜻한다.
DB에 한번 갔다온 엔티티
DB에 한번 저장되어 식별자가 존재하는 객체
이러한 준영속 엔티티는 JPA가 관리를 하지않기때문에 객체를 수정을 해도 DB에 Update가 일어나지 않는다.
준영속 엔티티가 무엇인지 감이 잘 안잡힐수있다. 예시를 통해 보자
Form 태그로 데이터 수정
//Controller
//1
@GetMapping("items/{itemId}/edit")
public String updateItemForm(@PathVariable("itemId") Long itemId, Model model){
Book item = (Book) itemService.findOne(itemId);
BookForm form = new BookForm();
form.setId(item.getId());
form.setName(item.getName());
...
form.setIsbn(item.getIsbn());
model.addAttribute("form", form);
return "items/updateItemForm";
}
//2
@PostMapping(value = "/items/{itemId}/edit")
public String updateItem(@ModelAttribute("form") BookForm form) {
Book book = new Book();
book.setId(form.getId());
book.setName(form.getName());
...
book.setIsbn(form.getIsbn());
itemService.saveItem(book);
return "redirect:/items";
<!--updateItemForm.html-->
<form th:object="${form}" method="post">
<input type="hidden" th:field="*{id}" />
<div class="form-group">
<label th:for="name">상품명</label>
<input type="text" th:field="*{name}" class="form-control" placeholder="이름을 입력하세요" />
</div>
...
예시 설명
질문 : 2번 updateItem 에서 book 객체의 수정사항이 변경감지(Dirty Checking)가 될까❓
➡️ 변경감지가 일어나지않는다.
위와 같은 예시에서는 변경감지가 일어나지 않는다. 왜냐하면 book객체는 준영속 엔티티 이기때문이다.
준영속 엔티티의 핵심은 식별자를 기준으로 영속상태가 되어 DB에 저장된적이 있는가 이다.
book객체는 이미 영속엔티티였던 form의 id값을 book.setId(form.getId())
하였으므로 준영속 엔티티인것이다.
이러한 준영속 엔티티를 수정하는 두가지 방법이있다.
service 계층게 메서드를 추가한다.
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다.
}
즉 변경감지기능 사용은 준영속 엔티티의 id로 해당 영속엔티티를 불러와 수정하는것이다.
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item mergeItem = em.merge(itemParam);
}
과정설명
코드로 표현을 해보자면 merge를 사용시 아래코드와 같은 일을 한다.
@Transactional
public Item update(Long itemId, Item itemParam) {
Item findItem = itemRepository.findOne(itemId);
findItem.setName(itemParam.getName());
...
return findItem;
}
하는 일은 병합과 변경 감지 기능이 비슷한데 병합에는 단점이 있다.
em.merge(item)
이런식으로 파라미터에 객체를 통채로 보낸다. 그러므로 특정 속성을 변경 할 수 없고 객체의 모든 속성을 변경해야한다.
모든 속성을 변경하는게 왜 단점이냐 라고 질문할수있는데 예시를 들어보겠다.
만약 item의 가격을 수정하고싶지않을 경우
: 준영속 엔티티를 변경할때는 항상 변경 감지를 사용해라