- 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 방식으로 받아온다.
- 보는 것과 같이 기존의 바다 사진에서 하늘 사진으로 변경된 것을 확인 할 수 있다.
'Portfolio, Project > Project(Programming)' 카테고리의 다른 글
Project (5-3) 메인 화면, 상품 상세 페이지 (1) (추가 내용 작성 필요할 듯...) (0) | 2023.08.11 |
---|---|
Project (5-2) 상품 관리 (1) (0) | 2023.08.11 |
Project (5-1) - 상품 등록 및 수정 (1) (0) | 2023.08.08 |
Project - (4) 연관관계 매핑 (0) | 2023.08.07 |
Project (3) - 스프링 시큐리티 (0) | 2023.08.03 |