JPA의 [준영속 엔티티]에 대한 [수정(update)] 전략은 2가지가 있다. (영속 엔티티라도 전략은 같음)
준영속 엔티티 : Context가 더 이상 관리하지 않는 엔티티.
-> 아래의 코드에서 보듯이, 임의로 만든 엔티티여도 [기존 식별자]를 가지고 있으면, [준영속] 엔티티라고 볼 수가 있다.
특징은, Context에서 관리되었던 엔티티의 [식별자]를 가지고 있다는 것!
1] 변경 탐지(dirty checking)
2] 병합(merge) : 절대로 사용하면 안 됨(이유는 아래에서 천천히 설명을 함)
-> JPA는 변경 탐지(Dirty Checking)을 [수정]의 전략으로 권장하는 [수정]의 Best Practice이며,
강사 왈 "병합(merge)는 실무에서 거의 사용하지 않는다" 라고 하심.
- Dirty Checking과 Merge의 차이점 -
( 이 둘의 개념과 차이점을 모르면, 개발 중 엄청나게 고생을 할 거라고 강조 또 강조를 하셨다. 꼭 숙지하자)
@PostMapping(value = "/items/{itemId}/edit") // [상품 목록] -> [수정] -> [수정] 페이지로부터 데이터를 받아서 업데이트!
public String updateItem(@PathVariable String itemId,@ModelAttribute("form") BookForm form) {
Book book = new Book();
book.setId(form.getId()); // 기존 [식별자]를 가지고 있으므로, 임의로 만든 book이지만 [준영속] 상태의 엔티티로 볼 수 있다(ppt 89)
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"; // [수정]이 완료되면, redirect
}
ItemService.saveItem()이 어떻게 정의돼 있나 확인을 해보자
@Transactional // readOnly == false
public void saveItem(Item item){
itemRepository.save(item);
}
이번에는 itemRepository.save()가 어떻게 정의돼 있는지 확인을 해보자.
public void save(Item item){
if(item.getId() == null){ // 해당 Item 객체는 [준영속]도 [영속] 엔티티도 아니다.
entityManager.persist(item);
}
else{ // 헤당 Item 객체는 [준영속] 엔티티이다.
entityManager.merge(item);
}
}
entityManager.merge(item)은 아래의 코드의 똑같이 동작을 한다.
@Transactional
public Item updateItem(Long itemId, Book book){ // book : [준영속] 엔티티, itemId : book의 [기존 식별자]
Item findITtem = itemRepository.findOne(itemId); // Context or DB에서 Item(Book) 가져옴.즉, findItem은 [영속] 엔티티이다.
findITtem.setPrice(book.getPrice());
findITtem.setName(book.getName());
findITtem.setStockQuantity(book.getStockQuantity());
return findItem;
//findItem은 Context에 의해 관리가 되고 있는 [영속] 엔티티이므로, 결과적으로는 [Dirty Checking]으로 [Merge]가 동작을 하여, 최종적으로 [수정]이 일어난다.
}
'CS 잡지식' 카테고리의 다른 글
DB에 저장(save)를 하고 나면, 반드시 id값을 반환을 하자!! (0) | 2023.05.03 |
---|---|
스프링 부트 3.X.X 버전에 따른 설정 변경 (0) | 2023.05.03 |
ThymeLeaf의 getter,setter 접근법(feat. *{객체의 속성}) (0) | 2023.05.02 |
view resource 등록하는 법(feat. bootstrap,jumbotron-narrow.css) (0) | 2023.05.02 |
인텔리J, 서버 실행 중 코드 수정(feat. Build -> recompile) (0) | 2023.05.02 |