6.2 상품 수정하기

선영·2022년 6월 12일
  1. 등록된 상품을 불러오는 메서드를 ItemService클래스에 추가
  • service > ItemService.java
    ... 기존 코드 생략 ... 
    @Transactional(readOnly = true)  //①
    public ItemFormDto getItemDtl(Long itemId) {
    
        List<ItemImg> itemImgList = itemImgRepository.findByItemIdOrderByIdAsc(itemId);  //②
        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.setItemImgIds(itemImgDtoList);

        return itemFormDto;
    }

① 상품 데이터를 읽어오는 트랜잭션을 읽기 전용으로 설정. 이럴 경우 JPA가 더티체킹(변경감지)을 수행하지 않아 성능을 향상시킬 수 있음.
② 해당 상품의 이미지를 조회. 등록순으로 가지고 오기 위해서 상품 이미지 아이디 오름순으로 가져옴.
③ 조회한 ItemImg 엔티티를 ItemImgDto 객체로 만들어서 리스트에 추가
④ 상품 아이디를 통해 상품 엔티티를 조회함. 존재하지 않을 때는 EntityNotFoundException 을 발생시킴.


  1. 상품 수정 페이지로 진입하기 위해서 ItemController 클래스에 코드를 추가. 실수에서는 등록 수정을 할 때 서버에 전달하는 데이터가 많이 다르기 때문에 보통 등록용 페이지와 수정용 페이지를 나눠서 개발함.
  • controller > ItemController.java
    @RequestMapping(value = "/admin/item/{itemId}", method = RequestMethod.GET)
    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/itemForm";
        }
        return "item/itemForm";
    }

① 조회한 상품 데이터를 모델에 담아서 뷰로 전달
② 상품 엔티티가 존재하지 않을 경우 에러메시지를 담아서 상품 등록 페이지로 이동


  1. 상품 이미지 수정을 위해 ItemImgService 클래스를 수정.
  • service > ItemImgService.java
... 기존 소스 생략 ...
public void updateItemImg(Long itemImgId, MultipartFile itemImgFile) throws Exception {

	// 지정한 이미지를 데이터베이스에서 조회
	if(!itemImgFile.isEmpty()) {  //①
    	ItemImg savedItemImg = itemImgRepository.findById(itemImgId)  //②
        .orElseThrow(EntityNotFoundException::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);  //⑤
        }
    }

① 상품 이미지를 수정한 경우 상품 이미지를 업데이트함.
② 상품 이미지 아이디를 이용하여 기존에 저장했던 상품 이미지 엔티티를 조회함.
③ 기존에 등록된 상품 이미지 파일이 있을 경우 해당 파일 삭제
④ 업데이트한 상품 이미지 파일을 업로드
⑤ 변경된 상품 이미지 정보를 세팅. 여기서 중요한 점은, 상품 등록 때처럼 itemImgRepository.save() 로직을 호출하지 않는다는 것. savedItemImg 엔티티는 현재 영속 상태이므로 데이터를 변경하는 것만으로 변경 감지 기능이 동작하면서 트랜잭션이 끝날 때 update 쿼리가 실행됨. 엔티티가 영속 상태여야 함!


  1. Item클래스에 상품 데이터를 업데이트 하는 로직 구현.
    엔티티 클래스에 비즈니스 로직을 추가하면 조금 더 객체지향적으로 코딩할 수 있고, 코드 재활용할 수 있음.
  • entity > Item.java
... 이전 코드 생략 ...
	public void updateItem(ItemFormDto itemFormDto) {
        this.itemNm = itemFormDto.getItemNm();
        this.price = itemFormDto.getPrice();
        this.stockNumber = itemFormDto.getStockNumber();
        this.itemDetail = itemFormDto.getItemDetail();
        this.itemSellStatus = itemFormDto.getItemSellStatus();
    }
  • service > ItemService.java
    public Long updateItem(ItemFormDto itemFormDto, List<MultipartFile> itemImgFileList) throws Exception {
        
        //상품수정
        Item item = itemRepository.findById(itemFormDto.getId()).orElseThrow(EntityNotFoundException::new);
        item.updateItem(itemFormDto);

        List<Long> itemImgIds = itemFormDto.getItemImgIdList();

        //이미지 등록
        for (int i = 0; i < itemImgFileList.size(); i++) {
            itemImgService.updateItemImg(itemImgIds.get(i), itemImgFileList.get(i));
        }
        return item.getId();
    }

① 상품 등록 화면으로부터 전달 받은 상품 아이디를 이용하여 상품 엔티티를 조회함.
② 상품 등록 화면으로부터 전달 받은 ItemFormDto를 통해 상품 엔티티를 업데이트함.
③ 상품 이미지 아이디 리스트를 조회함.
④ 상품 이미지를 업데이트하기 위해서 updateItemImg()메서드에 상품 이미지 아이디와 상품 이미지 파일 정보를 파라미터로 전달함.

  • controller > ItemController
    @RequestMapping(value = "/admin/item/{itemId}", method = RequestMethod.POST)
    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:/";
    }

① 상품 수정 로직을 호출함.



참고문헌 & 강의자료
변구훈, 스프링부트 쇼핑몰 프로젝트 with JPA, 로드북
(스마트혼합)자바&파이썬 빅데이터 웹UI콘텐츠 개발, 부산IT교육센터

0개의 댓글