import org.slf4j.Logger;
를 사용할 것@Slf4j
lombok 에서 해당 어노테이션 지원! 바로 코드에서 log 로 사용 가능!ctrl + shift + F9
으로 즉시 컴파일 가능!
ctrl + E
최근에 썼던 명령어, 리소스 뜸!
ctrl + alt + shift + T
리팩토링 관련 추천!
ctrl + shift + U
해당 문자 upper case 로 변환
영속성 컨텍스트에 올라와 있는 엔티티 에 대해서는, 어떤 변경들이 일어나더라도,
EntityManager 가 flush 되는 시점에 감지를 하여 sql 문이 날아간다.
but, 준영속 엔티티는 어떻게 해야하나?
- 영속성 컨텍스트가 더는 관리하지 않는 엔티티
- 하지만, jpa DB를 한번 거쳐서, 식별자는 가지고 있는 경우!
- 임의로 만든 엔티티 여도, 기존 식별자를 가지고 있으면,
준영속 엔티티
로 볼 수 있다.직접적으로 JPA 가 관리를 하지 않기에, 수정 이후 영속성 컨텍스트에 올려주어야함.
다른 방법은 없나? HOW?
- 변경 감지 기능
- 병합 (merge) 사용
@PostMapping("items/{itemId}/edit")
public String updateItem( @PathVariable String itemId, @ModelAttribute("form") BookForm form){
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";
}
@PostMapping("items/{itemId}/edit")
public String updateItem( @PathVariable String itemId, @ModelAttribute("form") BookForm form){
itemService.updateItem(itemId, form); // Service 계층에 메소드 추가
return "redirect:/items";
}
< ItemService.java >
@Transactional
public void updateItem(Long itemId, BookForm form){
Book book = (Book) itemRepository.findOne(itemId);
book.setName(form.getName());
book.setPrice(form.getPrice());
book.setStockQuantity(form.getStockQuantity());
book.setAuthor(form.getAuthor());
book.setIsbn(form.getIsbn());
}
이 부분도, 하나하나 setter 로 바꾸는 것 보다는, book 단의 Set Method 를 따로 만들어서, 하는 것을 추천!
우리 협업 좀 하자!! 몇달 뒤 너를 위해서라도! 동료 파트너를 위해서라도!
@Transactional
public void updateItem(Long itemId, BookForm form){
Book book = (Book) itemRepository.findOne(itemId);
book.changeWholeField(form.getName(),
form.getPrice(),
form.getStockQuantity(),
form.getAuthor(),
form.getIsbn());
}
< ItemRepository.java >
public void save(Item item){
if(item.getId() == null){
em.persist(item);
} else {
em.merge(item);
}
}
위의 변경감지랑 똑같은 flow 로 작동함!!
다만!!
불러온 값에서, merge 한 엔티티에 있는 값들로 전부 바꿔치기함!!
즉 영속성 컨텍스트 속에서는 내가 원하는 수정 상태로 가지고 있고, flush 하면 업데이트 sql 이 실행됨.
em.merge()
의 반환값을 사용해야함!!(1) 변경감지
를 사용하는 것이 맞음. 보통 update는 몇가지만 일어나니!!id
와 BookForm
을 service 계층에 파라미터로 전달@Transactional
을 가지고 있는 서비스 계층에서, 엔티티의 시작과 끝을 관리하는 것이 좋음< OrderController.java >
@PostMapping("/order")
public String order(@RequestParam("memberId") Long memberId,
@RequestParam("itemId") Long itemId,
@RequestParam("count") int count){
orderService.order(memberId, itemId, count);
return "redirect:/orders";
}
이런 식으로 service 계층에 엔티티를 직접 넘기지 않는 방법이 좋음!!