코드 그라데이션

shop 구현 (8) 상품 수정하기 / 변경감지 본문

Spring/SpringShop

shop 구현 (8) 상품 수정하기 / 변경감지

완벽한 장면 2023. 7. 14. 12:24

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 부르지 않아도 저장이 된다.

728x90
Comments