Portfolio, Project/Project(Programming)

Project (5-1) 상품 등록 및 수정 (2)

잇(IT) 2023. 8. 9. 22:31

- ItemService.java

@Transactional(readOnly = true)
    //상품 데이터를 읽어오는 트랜잭션을 읽기 전용을 설정한다.
    //JPA가 더티체킹(변경감지)을 수행하지 않아서 성능을 향상 시킬 수 있다.
    public ItemFormDto getItemDtl(Long itemId) {

        List<ItemImg> itemImgList = itemImgRepository.findByItemIdOrderByIdAsc(itemId);
        //해당 상품의 이미지를 조회한다. 등록순으로 가지고 오기 위해서 상품 이미지 아이디 오름차순으로 가지고 온다.
        List<ItemImgDto> itemImgDtoList = new ArrayList<>();
        for (ItemImg itemImg : itemImgList) {
            //조회한 ItemImg 엔티티를 ItemImgDto 객체로 만들어서 리스트에 추가한다.
            ItemImgDto itemImgDto = ItemImgDto.of(itemImg);
            itemImgDtoList.add(itemImgDto);
        }

        Item item = itemRepository.findById(itemId).orElseThrow(EntityNotFoundException::new);
        //상품의 아이디를 통해 상품 엔티티를 조회한다. 존재하지 않을 때는 EntityNotFoundException을 발생시킨다.
        ItemFormDto itemFormDto = ItemFormDto.of(item);
        itemFormDto.setItemImgDtoList(itemImgDtoList);
        return itemFormDto;
    }

- DB로부터 ItemImg와 Item을 가져와 DTO로 데이터를 넘긴다.

- ItemImgDto는 말 그대로 ItemImg 객체에 대한 데이터를 복사해서 받아오고

- ItemFormDto는 1~5개일 수 있는 이미지를 List로 받아서 ItemFromDto의 필드인 List에 담아서 저장한다.

 

- ItemController.java

@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/itemForm";
        }
        return "item/itemForm";
    }

- itemId를 @PathVariable로 받아 itemId를 파라미터로 넘기고, getItemDtl 메서드를 통해 ItemImgDto와 ItemFormDto를 가져온다. 추가로 itemFormDto는 model에 담아 view로 넘긴다.

 

- ItemImgService.java

- 상품 이미지 수정을 위해서 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);
            //변경된 상품 이미지 정보를 세팅해준다. 상품 등록 때처럼 itemImgRepository.save()로직을 호출하지 않는다.
            //savedItemImg 엔티티는 현재 영속 상태이므로 데이터를 변경하는 것만으로 변경 감지 기능이 동작하여 트랜잭션이 끝날 때
            //update 쿼리가 실행된다. 여기서 중요한 것은 엔티티가 영속 상태여야 한다는 것이다.
        }
    }

- itemImgId를 받아와 DB에서 해당 ItemImg를 가져온다.

- FileService 클래스의 deleteFile 클래스를 이용하여 해당 경로에 있는 이미지를 삭제한다.

- Post 방식으로 넘어온 새로운 ItemImg의 oriImgName(이미지 원본명)을 가져오고, FileService 클래스의 uploadFile 메서드를 이용하여 새로운 이미지를 해당 경로에 저장한다. 또한 새롭게 저장한 이미지의 주소를 저장한다.

- 즉, 기존의 이미지를 삭제하고 새로운 이미지를 저장하는 코드에 해당한다.

 

- 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();
    }
}

 

- ItemService.java

- 상품을 업데이트 할 때도 ItemImgService와 마찬가지로 변경 감지 기능을 사용한다.

...

public Long updateItem(ItemFormDto itemFormDto, List<MultipartFile> itemImgFileList) throws Exception {

        //상품 수정
        Item item = itemRepository.findById(itemFormDto.getId()).orElseThrow(EntityNotFoundException::new);
        //상품 등록 화면으로부터 전달 받은 상품 아이디를 이용하여 상품 엔티티를 조회한다.
        item.updateItem(itemFormDto);
        //상품 등록 화면으로부터 전달 받은 ItemFormDto를 통해 상품 엔티티를 업데이트 한다.

        List<Long> itemImgIds = itemFormDto.getItemImgIds();
        //상품 이미지 아이디 리스트를 조회한다.

        //이미지 등록
        for (int i = 0; i < itemImgFileList.size(); i++) {
            itemImgService.updateItemImg(itemImgIds.get(i), itemImgFileList.get(i));
            //상품 이미지를 업데이트하기 위해서 updateItemImg() 메소드에 상품 이미지 아이디와,
            //상품 이미지 파일 정보를 파라미터로 전달한다.
        }
        return item.getId();
    }
Item item = itemRepository.findById(itemFormDto.getId()).orElseThrow(EntityNotFoundException::new);
//상품 등록 화면으로부터 전달 받은 상품 아이디를 이용하여 상품 엔티티를 조회한다.
item.updateItem(itemFormDto);
//상품 등록 화면으로부터 전달 받은 ItemFormDto를 통해 상품 엔티티를 업데이트 한다.

List<Long> itemImgIds = itemFormDto.getItemImgIds();
//상품 이미지 아이디 리스트를 조회한다.

- 상품 수정을 위해서 ItemFormDto의 id를 통해 DB에서 해당 item을 조회해 온다.

- itemFormDto에 저장된 데이터 들을 item 객체에 복사해준다.

- 하나의 Item에는 여러개의 이미지들이 있기 때문에 해당 이미지들의 ID 값을 List로 저장한다.

//이미지 등록
        for (int i = 0; i < itemImgFileList.size(); i++) {
            itemImgService.updateItemImg(itemImgIds.get(i), itemImgFileList.get(i));
            //상품 이미지를 업데이트하기 위해서 updateItemImg() 메소드에 상품 이미지 아이디와,
            //상품 이미지 파일 정보를 파라미터로 전달한다.
        }
        return item.getId();
    }

- Post 방식으로 넘어온 여러 파일들은 List<MultipartFile> 리스트에 담기고 해당 List를 돌면서 이미지들을 itemImgService의 updateItemImg 메서드를 통해 이미지를 수정해준다.

- 수정이 전부 완료되면 수정이 완료된 item의 Id를 가져온다.

 

- ItemController.java

@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:/";
    }

- 상품을 수정하는 URL을 POST 방식으로 받아온다.

- 보는 것과 같이 기존의 바다 사진에서 하늘 사진으로 변경된 것을 확인 할 수 있다.

728x90