등록한 상품 정보를 볼 수 있는 상품 상세 페이지 및 상품 데이터 수정
상품을 등록하는 기능을 구현했다. 그러나 등록된 상품은 항상 수정이 가능하여야 할 것이다. 즉, 수정 기능을 구현해야한다. 기능을 만들기 위해 해야할 것들을 생각해보았다.
상품 이미지를 어떤 방식으로 조회할지에 대한 아이디어, ItemController
에서 조회한 상품을 통해 어떻게 수정 페이지에 들어가게끔 할 것인지에 대한 고민이 있었다.
(ItemService
단에서 ItemFormDto
를 주입 받아 등록된 상품들을 조회하는 메서드를 만들고, ItemController
에서는 ItemService
에서 만들어진 조회데이터로 model에 담아 view로 전달하게끔 하는 과정이 필요)
일단은 먼저 등록된 상품을 불러와야했고, 이를 위해 메소드를 ItemService
에 추가했다.
package com.shop.service;
// ..import 생략
@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;
}
}
EntityNotFoundException
을 발생시키도록 했다.다음은, 상품 수정 페이지로 진입하기 위한 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.java
@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
Entity는 현재 영속 상태이므로 데이터를 변경하는 것만으로 변경감지 기능이 동작하여 트랜잭션이 끝날 때 update 쿼리가 실행되기 때문이다. (Entity가 영속 상태일 때만 가능)
본격적으로 상품을 업데이트하는 로직을 구현하기 위해 첫번째로,
Item
class에 상품 데이터를 업데이트하는 로직을 만들었다.
Item.java
package com.shop.entity;
// import 생략
@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.java
@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
를 통해 상품 엔티티 업데이트updateItemImg()
메소드에 상품 이미지 아이디와 상품 이미지 파일 정보를 파라미터로 전달마지막으로 상품을 수정하는 URL을 ItemController
클래스에 추가했다.
ItemController.java
package com.shop.controller;
// ..import 생략
@Controller
@RequiredArgsConstructor
public class ItemController {
// 코드 생략
@PostMapping(value = "/admin/item/{itemId}")
public String itemUpdate(@Valid ItemFormDto itemFormDto, BindingResult bindingResult, Model model, @RequestParam("itemImgFile")
List<MultipartFile> itemImgFileList) {
if (bindingResult.hasErrors()) {
return "item/itemForm";
}
if (itemImgFileList.get(0).isEmpty() && itemFormDto.getId() == null) {
model.addAttribute("errorMessage", "첫번째 상품 이미지는 필수 입력 값입니다.");
return "item/itemForm";
}
try {
itemService.saveItem(itemFormDto, itemImgFileList);
} catch (Exception e) {
model.addAttribute("errorMessage", "상품 수정 중 에러가 발생하였습니다.");
return "item/itemForm";
}
return "redirect:/";
}
}
지금까지 상품을 등록하고 수정하는 기능을 구현했다. Entity 구현부터 Service단과 Controller단, 트랜잭션, 매핑관계 등등...을 모두 신경쓰다보니 할게 정말 많았다.😥 솔직히 혼자서 구현하기란 어려웠다. 그러나, 구글링과 도서들을 참고하여 만들다보니 비교적 쉽게 구현할 수 있었다. 무엇보다 구현이 잘되고 동작하는 것을 보니 나름 뿌듯했다. 여기서 그치지 않고 더욱 다양한 기능을 추가해 나만의 웹사이트를 구축해볼 생각이다.