[Spring Boot] 쇼핑몰 프로젝트 (11) - 상품 수정하기

YulHee Kim·2021년 12월 14일
0

Shopping mall 프로젝트

목록 보기
11/11

💡 상품 수정하기

✏️ 등록된 상품 상세 조회

ItemService.java

등록된 상품을 불러오는 메소드를 ItemService 클래스에 추가하겠습니다.

@Service
@Transactional
@RequiredArgsConstructor
public class ItemService {

    ...
    
    @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.setItemImgDtoList(itemImgDtoList);
        return itemFormDto;
    }
}

@Transactional(readOnly = true)은 상품 데이터를 읽어오는 트랜잭션을 읽기 전용으로 설정합니다. 이럴 경우 JPA가 더티체킹(변경감지)을 수행하지 않아서 성능을 향상 시킬 수 있습니다.

ItemController.java

상품 수정 페이지로 진입하기 위해 ItemController 클래스에 코드를 수정하겠습니다.

@Controller
@RequiredArgsConstructor
public class 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/itemForm";
        }

        return "item/itemForm";
    }
    
}

조회한 상품 데이터를 모델에 담아서 뷰로 전달합니다.

✏️ 상품 이미지 수정

상품 이미지 수정을 위해 ItemImgService 클래스를 수정하겠습니다. 변경감지 기능을 사용하겠습니다.

ItemImgService

@Service
@RequiredArgsConstructor
@Transactional
public class ItemImgService {

    ...

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

}

savedItemImg.updateItemImg(oriImgName, imgName, imgUrl); 은 변경된 상품 이미지 정보를 세팅해줍니다. 여기서 중요한 점은 상품 등록 때처럼 itemImgRepository.save()로직을 호출하지 않는다는 것입니다. savedItemImg 엔티티는 현재 영속 상태이므로 데이터를 변경하는 것만으로 변경 감지 기능이 동작하여 트랜잭션이 끝날 때 update 쿼리가 실행됩니다. 여기서 중요한 것은 엔티티가 영속 상태여야 한다는 것입니다.

✏️ 상품 업데이트 로직

Item 클래스

@Entity
@Table(name="item")
@Getter
@Setter
@ToString
public class Item {

    ...
    
    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


@Service
@Transactional
@RequiredArgsConstructor
public class ItemService {

     ...
     
     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.getItemImgIds();

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

        return item.getId();
    }
}

상품 등록 화면으로부터 전달 받은 ItemFormDto를 통해 상품 엔티티를 업데이트합니다.

ItemController

@Controller
@RequiredArgsConstructor
public class ItemController {

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

itemService.updateItem(itemFormDto, itemImgFileList); 로 상품 수정 로직을 호출합니다.

profile
백엔드 개발자

0개의 댓글