// 상품 삭제
@Transactional
public void deleteProduct(Long userId, Long productId) {
Product product = getProductWithSellerCheck(productId, userId);
// 1. 관련 조회수 데이터 삭제
viewCountRepository.deleteByProductId(productId);
// 2. 관련 위시리스트 데이터 삭제
wishlistRepository.deleteByProductId(productId);
// 3. 리뷰 데이터 삭제 (비즈니스 요구사항에 따라)
reviewRepository.findByProduct(product).ifPresent(reviewRepository::delete);
// 4. 이미지 파일 삭제를 위한 URL 수집
List<String> imageUrls = new ArrayList<>();
List<String> thumbnailUrls = new ArrayList<>();
// 이미지 URL 수집
for (ProductImage image : product.getImages()) {
imageUrls.add(image.getImageUrl());
thumbnailUrls.add(image.getThumbnailUrl());
}
try {
// 5. 상품 삭제 (이미지 엔티티도 cascade로 함께 삭제됨)
productRepository.delete(product);
// 6. 파일 시스템에서 이미지 파일 삭제
for (String url : imageUrls) {
fileStorageService.deleteFile(url);
}
for (String url : thumbnailUrls) {
fileStorageService.deleteFile(url);
}
log.info("상품 삭제 완료: 상품 ID {}, 판매자 ID {}", productId, userId);
} catch (Exception e) {
log.error("상품 삭제 중 오류 발생: 상품 ID {}, 원인: {}", productId, e.getMessage(), e);
throw new ProductException.ProductDeletionException(e.getMessage());
}
}
상품 삭제 로직 개선
ProductManagementService의 deleteProduct 메서드를 완전히 재구현했다. @Modifying
@Query("DELETE FROM ProductViewCount pvc WHERE pvc.product.id = :productId")
void deleteByProductId(@Param("productId") Long productId);
productId에 해당하는 상품의 조회수 기록(ProductViewCount) 을 삭제하는 쿼리다.
@Modifying
@Query("DELETE FROM ProductWishlist pw WHERE pw.product.id = :productId")
void deleteByProductId(@Param("productId") Long productId);
public static class ProductDeletionException extends ProductException {
public ProductDeletionException(String message) {
super("상품 삭제 중 오류가 발생했습니다: " + message, HttpStatus.INTERNAL_SERVER_ERROR, "PRODUCT_DELETION_FAILED");
}
}