코드 그라데이션
shop 구현 (8) 상품 수정하기 / 변경감지 본문
ItemController
추가된 부분
@GetMapping(value = "/admin/item/{itemId}")
public String itemDtl(@PathVariable("itemId")Long itemId, Model model) {
try {
ItemFormDto itemFormDto = itemService.getItemDtl(itemId);
model.addAttribute("itemFormDto", itemFormDto);
} catch (EntityNotFoundException e) {
model.addAttribute("errorMessage", "존재하지 않는 상품입니다.");
model.addAttribute("itemFormDto", new ItemFormDto());
return "item/itmeForm";
}
return "item/itemForm";
}
@PostMapping(value = "/admin/item/{itemId}")
public String itemUpdate(@Valid ItemFormDto itemFormDto, BindingResult bindingResult,
@RequestParam("itemImgFile") List<MultipartFile> itemImgFileList, Model model) {
if (bindingResult.hasErrors()) {
return "/item/itemForm";
}
if (itemImgFileList.get(0).isEmpty() && itemFormDto.getId() == null ) {
model.addAttribute("errorMessage", "첫번째 상품 이미지는 필수 입력 값 입니다.");
return "/item/itemForm";
}
try {
itemService.updateItem(itemFormDto, itemImgFileList);
} catch (Exception e) {
model.addAttribute("errorMessage", "상품 수정 중 에러 발생하였습니다.");
return "item/itemForm";
}
return "redirect:/";
}
조회와 수정.
조회할 때는 위처럼 Dto를 넘긴다. 엔티티 자체를 넘기지 않는다.
업데이트도 등록과 비슷하게 사용자가 무언가를 수정하는 것이니까
수정된 값이 최종적으로 내가 저장할 데이터베이스에 유효한지를 검사해야해서 @Valid ItemFormDto itemFormDto 여기 valid가 들어갈 수 밖에 없다. 거의 짝꿍처럼 bindingResult 따라온다.
Item
여기가 굉장히 지리한 과정인데
private String requestDetail;
public void updateItem(ItemFormDto itemFormDto) {
this.itemNm = itemFormDto.getItemNm();
this.price = itemFormDto.getPrice();
this.stockNumber = itemFormDto.getStockNumber();
this.itemDetail = itemFormDto.getItemDetail();
this.requestDetail = itemFormDto.getRequestDetail();
this.itemSellStatus = itemFormDto.getItemSellStatus();
}
Dto로 받은 것을 엔티티로 바꾸려면
하나씩 꺼내서 엔티티 요소에 넣어주는 과정을 반복해야한다.
이게 ModelMapper가 도와줬던 역할.
ItemImgService
public void updateItemImg(Long itemImgId, MultipartFile itemImgFile) throws Exception {
if(!itemImgFile.isEmpty()) { // 상품의 이미지를 수정한 경우 상품 이미지 업데이트
ItemImg savedItemImg = itemImgRepository.findById(itemImgId).orElseThrow(
EntityExistsException::new); // 기존 엔티티 조회
if (!StringUtils.isEmpty(savedItemImg.getImgName())) {
fileService.deleteFile(itemImgLocation + "/" +savedItemImg.getImgName());
}
String oriImgName = itemImgFile.getOriginalFilename();
String imgName = fileService.uploadFile(itemImgLocation, oriImgName, itemImgFile.getBytes()); // 파일 업로드
String imgUrl = "/images/item" + imgName;
savedItemImg.updateItemImg(oriImgName, imgName,imgUrl); // 이것 역시 save 부르지 않고 변경감지로 변경만 됨.
}
이미지 업데이트하는 것은 이미 있는 걸 변경하는 것이기 때문에 따로 저장절차 필요 없이 업데이트 한 번만 날려주면 되는 것
더티 체킹
즉, 이래서 개발자가 DB로 보내달라고 따로 요청을 하지 않아도 되는 것.
ItemService
@Transactional(readOnly = true)
public ItemFormDto getItemDtl(Long itemId){
List<ItemImg> itemImgList = itemImgRepository.findByItemIdOrderByIdAsc(itemId);
// DB에서 데이터를 가지고 옵니다.
List<ItemImgDto> itemImgDtoList = new ArrayList<>();
for (ItemImg itemImg : itemImgList) {
ItemImgDto itemImgDto = ItemImgDto.of(itemImg);
itemImgDtoList.add(itemImgDto);
}
Item item = itemRepository.findById(itemId)
.orElseThrow(EntityNotFoundException::new);
ItemFormDto itemFormDto = ItemFormDto.of(item);
itemFormDto.setItemImgDtoList(itemImgDtoList);
return itemFormDto;
}
조회할 때도 Dto를 전달해야 하기 때문에
이미지 가져와서 하나하나 ItemImgDto로 바꿔주는 과정이 필요. ItemFormDto.of(item)
그다음에 아이탬 가져온 다음에 하나하나 아이템에 이미지 꽂아주고
=> 엔티티를 한 번도 그대로 쓴 적이 없다.
그리고
@Transactional(readOnly = true) 기본적으론 false인데 true로 설정했다는 건 읽기 전용이니까 수정 x
스냅샷을 찍을 필요가 없다.
여기도 마찬가지인데
// 수정 만들기
public Long updateItem(ItemFormDto itemFormDto, List<MultipartFile> itemImgFileList) throws Exception {
Item item = itemRepository.findById(itemFormDto.getId()).orElseThrow(EntityExistsException::new);
item.updateItem(itemFormDto); // save 따로 부르지 않아도 변경이 됨.
List<Long> itemImgIds = itemFormDto.getItemImgIds();
for (int i =0; i<itemImgFileList.size();i++) {
itemImgService.updateItemImg(itemImgIds.get(i), itemImgFileList.get(i));
}
return item.getId();
}
save 안 불러도 저장 된 이유는
얘가 Transactional이고 영속 상태로 가져왔기 때문에 itemRepository.findById(itemFormDto.getId()) 변경사항이 자동으로 감지가 돼서 트랜잭션이 끝날
따로 save 부르지 않아도 저장이 된다.
'Spring > SpringShop' 카테고리의 다른 글
shop 구현 (10) 상품 관리하기 페이지 (0) | 2023.07.15 |
---|---|
shop 구현 (9) 특이한 상속구조 (0) | 2023.07.14 |
shop 구현 (7) 상품 등록 (0) | 2023.07.13 |
shop 구현 (6) Auditing (0) | 2023.07.12 |
shop 구현 (5) 고아객체 제거, 즉시 로딩과 지연 로딩 (0) | 2023.07.12 |