본문 바로가기
Library&Framework/Spring Boot

[Spring Boot]상품 더미데이터 만들기 - (2)유틸 클래스와 기능 설명[상품, 이미지, 카테고리, 색상, 인벤토리 등]

by 우지uz 2024. 7. 29.

Spring Boot 애플리케이션에서 상품 더미데이터 유틸 클래스와 기능 설명

소개

안녕하세요! 이번 포스팅에서는 Spring Boot 애플리케이션에서 상품 더미데이터를 생성하는 각 유틸 클래스의 기능과 코드에 대해 자세히 설명드리겠습니다. 각 클래스의 역할과 주요 메서드, 코드의 의미를 이해하고 실제 애플리케이션에서 더미데이터를 생성하여 활용하는 방법을 다룹니다.

대상 독자

이 글은 Spring Boot 애플리케이션을 개발한 경험이 있는 개발자분들을 대상으로 합니다. 기본적인 Spring Boot 설정과 JPA, Lombok 등의 라이브러리에 대한 이해가 필요합니다.

목차
1. 상품 더미데이터 초기화 클래스
 - ProductInitializer 클래스 개요
2. 데이터 생성 유틸 클래스에서 각 메서드에 대한 간단한 설명!
 - ProductDataUtil 클래스
      - 상품 데이터 생성 메서드
      - 이미지 경로 처리 및 상품 정보 설정
상품 저장 메서드
 - ProductThumbnailDataUtil 클래스
      - 썸네일 데이터 생성 메서드
      - 썸네일 저장 메서드
 - CategoryDataUtil 클래스
      - 카테고리 데이터 생성 메서드
      - 부모/자식 카테고리 설정
 - ProductColorDataUtil 클래스
      - 색상 데이터 생성 및 저장 메서드
 - ProductManagementDataUtil 클래스
      - 상품 관리 데이터 생성 메서드
      - 재고, 사이즈 등 설정
3. 실제 코드 설명과 예제
 - 각 클래스의 주요 메서드 설명
 - 코드의 주요 부분과 의미
 - 예제 코드와 실행 결과
4. 실제 데이터베이스에 데이터 삽입하기
 - 애플리케이션 실행 및 결과 확인
 - 데이터베이스 초기화 확인
 - 생성된 더미 데이터 확인 방법
5. 마무리 및 팁
 - 실제 프로젝트에서 더미 데이터 활용 방법
 - 테스트 환경에서의 더미 데이터 관리 팁
 - 추가 개선 사항 및 확장 방법

1. 상품 더미데이터 ProductInitializer 클래스 개요

@Component
@Profile("develop")
@Order(1)
@RequiredArgsConstructor
public class ProductInitializer implements ApplicationRunner {

    // 더미데이터 생성 및 DB 저장역할을 하는 Util Class
    private final ProductDataUtil productDataUtil;
    private final ProductThumbnailDataUtil thumbnailDataUtil;
    private final CategoryDataUtil categoryDataUtil;
    private final ProductColorDataUtil productColorDataUtil;
    private final ProductManagementDataUtil productManagementDataUtil;

    @Override
    public void run(ApplicationArguments args) throws Exception {

        // 상품 더미 데이터 생성후, 더미 데이터 DB 저장
        List<Product> products = productDataUtil.generateProductDataWithImages(imagePaths);

        // 상품 썸네일 더미 데이터 생성후, 더미 데이터 DB 저장
        thumbnailDataUtil.generateProductThumbnailDataV3(products, imagePaths);

        // 카테고리 데이터 (34개)
        List<Category> categories = categoryDataUtil.generateCategoryData();

        // 상품 색상 더미데이터 생성후, 더미 데이터 DB 저장
        List<ProductColor> productColors = productColorDataUtil.generateAndSaveProductColorData();

        // 상품 관리 더미데이터 생성후, 더미 데이터 DB 저장
        productManagementDataUtil.generateProductManagementData(products, imagePaths, productColors, categories);
    }

	// 이미지 파일 이름을 Array 로 저장했습니다. 터미널에서 해당 디렉토리로 이동해서, 파일 이름전체를 출력하고 
    // 파일 이름을 String 값 Array 로 저장하도록 Chat GPT 에게 요청했습니다.
    List<String> imagePaths = Arrays.asList(
            "accessories_bag_1.jpg", "outer_cardigan_2.jpg", "shoes_sneakers_1.jpg",
            "accessories_bag_2.jpg", "outer_coat_1.jpg", "shoes_sneakers_2.jpg",
            "accessories_cap_1.jpg", "outer_coat_2.jpg", "top_blouse_1.jpg",
            "accessories_cap_2.jpg", "outer_jacket_1.jpg", "top_blouse_2.jpg",
            "accessories_socks_1.jpg", "outer_jacket_2.jpg", "top_hoodie_1.jpg",
            "accessories_socks_2.jpg", "outer_lightweight-padding_1.jpg","top_hoodie_2.jpg",
            "bottom_long_1.jpg", "outer_lightweight-padding_2.jpg", "top_knit-sweater_1.jpg",
            "bottom_long_2.jpg", "outer_long-padding_1.jpg", "top_knit-sweater_2.jpg",
            "bottom_shorts_1.jpg", "outer_long-padding_2.jpg", "top_long-shirts_1.jpg",
            "bottom_shorts_2.jpg", "outer_mustang_1.jpg", "top_long-shirts_2.jpg",
            "bottom_skirt_1.jpg", "outer_mustang_2.jpg", "top_long-sleeve_1.jpg",
            "bottom_skirt_2.jpg", "outer_short-padding_1.jpg", "top_long-sleeve_2.jpg",
            "dress&set_dress_1.jpg", "outer_short-padding_2.jpg", "top_short-shirts_1.jpg",
            "dress&set_dress_2.jpg", "outer_vest_1.jpg", "top_short-shirts_2.jpg",
            "dress&set_set-up_1.jpg", "outer_vest_2.jpg", "top_short-sleeve_1.jpg",
            "dress&set_set-up_2.jpg", "shoes_boots_1.jpg", "top_short-sleeve_2.jpg",
            "dress&set_two-piece_1.jpg", "shoes_boots_2.jpg", "top_sweatshirt_1.jpg",
            "dress&set_two-piece_2.jpg", "shoes_sandal_1.jpg", "top_sweatshirt_2.jpg",
            "outer_cardigan_1.jpg", "shoes_sandal_2.jpg"
    );
}

각 코드에 대한 설명을, 주석에 달아주었습니다. 
다음으로, 각 더미데이터 유틸 클래스에 대한 메서드의 역할에 대해 간단히 설명드리겠습니다.

2. 데이터 생성 유틸 클래스에서 각 메서드에 대한 요약

각 유틸 클래스에서는, 다음과 같은 기능들이 존재합니다. 자세한 코드 및 설명은 다음 목차에서 진행됩니다.

ProductDataUtil 클래스

  • generateProductDataWithImages(List<String> imagePaths): 이미지 경로를 받아 상품 데이터를 생성하고 저장합니다.
public List<Product> generateProductDataWithImages(List<String> imagePaths) {
    return imagePaths.stream()
            .map(this::createProductFromImagePath)
            .map(this::saveProduct)
            .collect(Collectors.toList());
}
  • createProductFromImagePath(String imagePath): 이미지 경로로부터 상품을 생성합니다. 카테고리, 서브카테고리, 가격, 제조업체, 할인 여부 등을 설정합니다.
private Product createProductFromImagePath(String imagePath) {
    String[] splitPath = imagePath.split("_");
    String category = splitPath[0];
    String subCategory = splitPath[1];

    Random rand = new Random();

    // 제조업체 . 실제 존재하지 않습니다.
    String[] manufacturers = {
            "FashionThreads Inc",
            "Elite Apparel Co",
            "Stylish Stitches Ltd",
            "Urban Garments Manufacturing",
            "ChicWear Productions",
            "TrendSet Clothing Co",
            "Elegant Fabrics Ltd"
    };
    // 가격을 100, 200, 300, 400, 500 중에서 랜덤하게 select.
    int[] prices = {200, 300, 400};
    int[] discountRates = {10, 20, 30, 40, 50};

    int price = prices[rand.nextInt(prices.length)];
    String manufacturer = manufacturers[rand.nextInt(manufacturers.length)];
    ProductType productType = getProductType(subCategory);

    // isDiscount 여부에 따라, discountRate 를 정해주도록 [24.06.03]
    boolean isDiscount = rand.nextBoolean(); // 할인 여부
    Integer discountRate;
    if (isDiscount) {
        discountRate = discountRates[rand.nextInt(discountRates.length)];
    } else {
        discountRate = null;
    }
    boolean isRecommend = rand.nextBoolean(); // 추천 상품 여부

    String productName = buildProductName(manufacturer, productType, subCategory, discountRate);
    String productInfo = "This is a " + productType.toString().toLowerCase() + " product for " + subCategory;

    // You might want to set imagePath to your product here if you have such field in your Product entity
    return new Product(productName, productType, price, productInfo, manufacturer, isDiscount, discountRate, isRecommend);
}
  • buildProductName(String manufacturer, ProductType productType, String subCategory, Integer discountRate) : 제조사, 성별, 하위카테고리, 할인률을 기반으로 상품 이름을 저장합니다.
private String buildProductName(String manufacturer, ProductType productType, String subCategory, Integer discountRate) {
    String adjective = getAdjectiveForSubCategory(subCategory);
    String discountText = (discountRate != null) ? " [" + discountRate + "% 할인특가]" : "";
    return String.format("[%s] %s %s %s%s", manufacturer, productType, adjective, subCategory, discountText);
}

private String getAdjectiveForSubCategory(String subCategory) {
    return switch (subCategory) {
        case "blouse" -> "Elegant";
        case "skirt" -> "Chic";
        case "dress" -> "Graceful";
        case "two-piece" -> "Sophisticated";
        case "short-padding" -> "Warm";
        case "long-padding" -> "Full-body warmth";
        case "lightweight-padding" -> "Light";
        case "boots" -> "Sturdy";
        case "sandal" -> "Breezy";
        case "sneakers" -> "Sporty";
        case "hoodie" -> "Casual";
        case "knit-sweater" -> "Snug";
        case "sweatshirt" -> "Relaxed";
        case "long-shirts" -> "Formal";
        case "short-shirts" -> "Cool";
        case "long-sleeve" -> "Comfy";
        case "short-sleeve" -> "Breathable";
        case "shorts" -> "Athletic";
        case "long" -> "Flowy";
        case "set-up" -> "Coordinated";
        case "cardigan" -> "Layered";
        case "coat" -> "Classic";
        case "jacket" -> "Stylish";
        case "vest" -> "Versatile";
        case "cap" -> "Trendy";
        case "socks" -> "Cozy";
        case "bag" -> "Fashionable";
        default -> "Unique";
    };
}
  • saveProduct(Product product): 생성된 상품을 데이터베이스에 저장합니다.
private Product saveProduct(Product product) {
    try {
        return productRepository.save(product);
    } catch (DataIntegrityViolationException ex) {
        if (ex.getCause() instanceof ConstraintViolationException constraintException) {
            log.error("Constraint violation for Product: " + product.toString(), constraintException.getSQLException());
        }
        throw ex;
    }
}

ProductThumbnailDataUtil 클래스

  • generateProductThumbnailDataV3(List<Product> products, List<String> imagePaths): 상품 리스트와 이미지 경로 리스트를 받아 상품 썸네일 데이터를 생성하고 저장합니다.
public void generateProductThumbnailDataV3(List<Product> products, List<String> imagePaths) {
    if(imagePaths.size() != products.size()) {
        throw new IllegalArgumentException("The number of products and image paths should be equal");
    }

    for (int i = 0; i < products.size(); i++) {
        // 이미지 경로 생성
        String imagePath = String.format("/uploads/thumbnails/%s", imagePaths.get(i));
        // 상품 추출
        Product product = products.get(i);
        // 썸네일 생성 및 저장
        ProductThumbnail productThumbnail = new ProductThumbnail(product, imagePath);
        productThumbnailRepository.save(productThumbnail);
    }
}

CategoryDataUtil 클래스

  • generateCategoryData(): 카테고리 데이터를 생성하고 저장합니다. 상위 카테고리와 그 상위 카테고리의 하위 카테고리들로 순서대로 저장해주었습니다. 기획단계에서 1차적으로 결정한 카테고리 데이터입니다. 추후 추가하고 싶은 카테고리 데이터가 있으면, 현재 카테고리 데이터에서 추가하면 됩니다. 
public List<Category> generateCategoryData() {
    List<Category> categories = new ArrayList<>();

    // top, bottom, dress&set, outer, shoes, accessories 순서
    // "상의"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
    List<Category> topsChildren = new ArrayList<>();
    Category topParentCategory = createAndSaveParentCategory(1L, "top", new ArrayList<>());
    Category blouse = createAndSaveChildCategoryV2(2L, "blouse", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(blouse);
    Category hoodie = createAndSaveChildCategoryV2(3L, "hoodie", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(hoodie);
    Category knitSweater = createAndSaveChildCategoryV2(4L, "knit-sweater", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(knitSweater);
    Category longShirts = createAndSaveChildCategoryV2(5L, "long-shirts", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(longShirts);
    Category longSleeve = createAndSaveChildCategoryV2(6L, "long-sleeve", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(longSleeve);
    Category shortShirts = createAndSaveChildCategoryV2(7L, "short-shirts", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(shortShirts);
    Category shortSleeve = createAndSaveChildCategoryV2(8L, "short-sleeve", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(shortSleeve);
    Category sweatshirt = createAndSaveChildCategoryV2(9L, "sweatshirt", topParentCategory.getCategoryId(), new ArrayList<>());
    topsChildren.add(sweatshirt);
    topParentCategory.setChildren(topsChildren);

    // "하의"에 하위 카테고리 생성
    List<Category> bottomChildren = new ArrayList<>();
    Category bottomParentCategory = createAndSaveParentCategory(10L, "bottom", new ArrayList<>());
    Category longBottom = createAndSaveChildCategoryV2(11L, "long", bottomParentCategory.getCategoryId(), new ArrayList<>());
    bottomChildren.add(longBottom);
    Category shorts = createAndSaveChildCategoryV2(12L, "shorts", bottomParentCategory.getCategoryId(), new ArrayList<>());
    bottomChildren.add(shorts);
    Category skirt = createAndSaveChildCategoryV2(13L, "skirt", bottomParentCategory.getCategoryId(), new ArrayList<>());
    bottomChildren.add(skirt);
    bottomParentCategory.setChildren(bottomChildren);

    // "dress&set"에 하위 카테고리 생성
    List<Category> dressChildren = new ArrayList<>();
    Category dressParentCategory = createAndSaveParentCategory(14L, "dress&set", new ArrayList<>());
    Category dress = createAndSaveChildCategoryV2(15L, "dress", dressParentCategory.getCategoryId(), new ArrayList<>());
    dressChildren.add(dress);
    Category setUp = createAndSaveChildCategoryV2(16L, "set-up", dressParentCategory.getCategoryId(), new ArrayList<>());
    dressChildren.add(setUp);
    Category twoPiece = createAndSaveChildCategoryV2(17L, "two-piece", dressParentCategory.getCategoryId(), new ArrayList<>());
    dressChildren.add(twoPiece);
    dressParentCategory.setChildren(dressChildren);

    // "아우터"에 대한 하위 카테고리 생성 후, 하위 카테고리로 다음을 추가
    List<Category> outerChildren = new ArrayList<>();
    Category outerParentCategory = createAndSaveParentCategory(18L, "outer", new ArrayList<>());
    Category cardigan = createAndSaveChildCategoryV2(19L, "cardigan", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(cardigan);
    Category coat = createAndSaveChildCategoryV2(20L, "coat", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(coat);
    Category jacket = createAndSaveChildCategoryV2(21L, "jacket", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(jacket);
    Category lightweightPadding = createAndSaveChildCategoryV2(22L, "lightweight-padding", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(lightweightPadding);
    Category longPadding = createAndSaveChildCategoryV2(23L, "long-padding", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(longPadding);
    Category mustang = createAndSaveChildCategoryV2(24L, "mustang", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(mustang);
    Category shortPadding = createAndSaveChildCategoryV2(25L, "short-padding", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(shortPadding);
    Category vest = createAndSaveChildCategoryV2(26L, "vest", outerParentCategory.getCategoryId(), new ArrayList<>());
    outerChildren.add(vest);
    outerParentCategory.setChildren(outerChildren);

    // "신발"에 대한 하위 카테고리 생성 후, 하위 카테고리로 다음을 추가
    List<Category> shoesChildren = new ArrayList<>();
    Category shoesParentCategory = createAndSaveParentCategory(27L, "shoes", new ArrayList<>());
    Category boots = createAndSaveChildCategoryV2(28L, "boots", shoesParentCategory.getCategoryId(), new ArrayList<>());
    shoesChildren.add(boots);
    Category sandal = createAndSaveChildCategoryV2(29L, "sandal", shoesParentCategory.getCategoryId(), new ArrayList<>());
    shoesChildren.add(sandal);
    Category sneakers = createAndSaveChildCategoryV2(30L, "sneakers", shoesParentCategory.getCategoryId(), new ArrayList<>());
    shoesChildren.add(sneakers);
    shoesParentCategory.setChildren(shoesChildren);

    // "악세사리"에 대한 하위 카테고리 생성 후, 하위 카테고리로 다음을 추가
    List<Category> accessoryChildren = new ArrayList<>();
    Category accessoryParentCategory = createAndSaveParentCategory(31L, "accessories", new ArrayList<>());
    Category bag = createAndSaveChildCategoryV2(32L, "bag", accessoryParentCategory.getCategoryId(), new ArrayList<>());
    accessoryChildren.add(bag);
    Category cap = createAndSaveChildCategoryV2(33L, "cap", accessoryParentCategory.getCategoryId(), new ArrayList<>());
    accessoryChildren.add(cap);
    Category socks = createAndSaveChildCategoryV2(34L, "socks", accessoryParentCategory.getCategoryId(), new ArrayList<>());
    accessoryChildren.add(socks);
    accessoryParentCategory.setChildren(accessoryChildren);

    // Add constructed parent categories to categories list
    categories.addAll(topParentCategory.getChildren());
    categories.addAll(bottomParentCategory.getChildren());
    categories.addAll(dressParentCategory.getChildren());
    categories.addAll(outerParentCategory.getChildren());
    categories.addAll(shoesParentCategory.getChildren());
    categories.addAll(accessoryParentCategory.getChildren());

    System.out.println("categories = " + categories);
    return categories;
}
  • createAndSaveParentCategory(Long categoryId, String name, List<Category> children): 부모 카테고리를 생성하고 저장합니다.
private Category createAndSaveParentCategory(Long categoryId, String name, List<Category> children) {
    // DB 에 이미 존재하는 category Id 인지 확인한다.
    Optional<Category> optionalCategory = categoryRepository.findByCategoryId(categoryId);

    if (optionalCategory.isPresent()) {
        return optionalCategory.get();
    } else {
        Category category = Category.createCategoryDummyData(categoryId, name, 0L, children);
        children.forEach(child -> child.setParent(category));
        category.setChildren(children);
        categoryService.createCategory(category, null);
        return category;
    }
}
  • createAndSaveChildCategoryV2(Long categoryId, String name, Long parentId, List<Category> children): 자식 카테고리를 생성하고 저장합니다.
protected Category createAndSaveChildCategoryV2(Long categoryId, String name, Long parentId, List<Category> children) {
    // DB에 이미 존재하는 category Id인지 확인한다.
    Optional<Category> optionalCategory = categoryRepository.findByCategoryId(categoryId);

    if(optionalCategory.isPresent()){
        // If category already exists, return it
        return optionalCategory.get();
    } else {
        Category category = Category.createChildCategory(categoryId, name, 1L, children);

        if (parentId != null) {
            Category parentCategory = categoryRepository.findById(parentId).orElseThrow(() ->
                    new RuntimeException("부모 카테고리를 찾을 수 없습니다. ID: " + parentId));
            category.setParent(parentCategory);
        }

        categoryService.createCategory(category, parentId);
        return category;
    }
}

ProductColorDataUtil 클래스

  • generateAndSaveProductColorData(): 색상 데이터를 생성하고 저장합니다.
public List<ProductColor>  generateAndSaveProductColorData() {
    // Red, Orange, Yellow, Green, Blue, Navy, Purple, Black, White, Gray, Pink, Ivory, Beige, Rainbow
    return Arrays.asList(
            createAndSaveProductColor("Red"),
            createAndSaveProductColor("Orange"),
            createAndSaveProductColor("Yellow"),
            createAndSaveProductColor("Green"),
            createAndSaveProductColor("Blue"),
            createAndSaveProductColor("Navy"),
            createAndSaveProductColor("Purple"),
            createAndSaveProductColor("Black"),
            createAndSaveProductColor("White"),
            createAndSaveProductColor("Gray"),
            createAndSaveProductColor("Pink"),
            createAndSaveProductColor("Ivory"),
            createAndSaveProductColor("Beige"),
            createAndSaveProductColor("Rainbow")
    );
}
  • createAndSaveProductColor(String color): 주어진 색상을 데이터베이스에 저장합니다.
private ProductColor createAndSaveProductColor(String color) {
    Optional<ProductColor> existingProductColor = productColorRepository.findByColor(color);
    if (existingProductColor.isEmpty()) {
        ProductColor productColor = new ProductColor(color);
        return productColorRepository.save(productColor);
    } else {
        return existingProductColor.get();
    }
}

ProductManagementDataUtil 클래스

  • generateProductManagementData(List<Product> products, List<String> imagePaths, List<ProductColor> colors, List<Category> categories): 주어진 상품, 이미지 경로, 색상, 카테고리를 기반으로 상품 인벤토리 데이터를 생성하고 저장합니다.
    imagePaths 는 상품 이미지 파일을, 리스트한 데이터죠. ProductInitailizer 에서 설명드렸던 이미지 리스트 데이터입니다. 
    이미지 파일의 갯수에 맞게, 상품, 이미지, 상품 색상과 사이즈를 적용하면 되는데요
@Transactional
public void generateProductManagementData(List<Product> products, List<String> imagePaths, List<ProductColor> colors, List<Category> categories) {
    // Get three random colors
    List<ProductColor> randomColors = getRandomThreeColors(colors);

    for (int i = 0; i < imagePaths.size(); i++) {
        // 상품 n 번 + 썸네일 n 번, 색상 3가지에 대해서 상품인벤토리 생성
        String imagePath = imagePaths.get(i);
        Product product = products.get(i);
        // 랜덤한 3가지 색상에 대해 ProductManagement 생성.
        for (ProductColor color : randomColors) {
            ProductManagement productManagement = createProductManagementV2(product, imagePath, color, categories);
            productManagementRepository.save(Objects.requireNonNull(productManagement));
        }
    }
}

private List<ProductColor> getRandomThreeColors(List<ProductColor> colors) {
    Collections.shuffle(colors);
    return colors.stream().limit(3).collect(Collectors.toList());
}
  • createProductManagementV2(Product product, String imagePath, ProductColor color, List<Category> categories): 상품, 이미지 경로, 색상, 카테고리를 기반으로 상품 인벤토리 데이터를 생성합니다.

여기서 String[] splitPath = imagePath.split("_"); 를 통해서, 카테고리를 추출했고 (이미지 파일 이름 자체에, 하위 카테고리를 일부러 넣었죠?) 이미지파일을 토대로 상품 이름, 카테고리, 혹은 수식어(Adjective)를 달아주었습니다. 

보통 쇼핑몰 사이트에 들어가보면, 특정 상품의 "포인트" , 즉 그 상품의 멋스러움을 상품 이름에 적용시켰더라구요. 
그래서 , 더미데이터에 어떻게 적용할 수 있을까?? 고민하다가 

private String getAdjectiveForSubCategory(String subCategory) {
    return switch (subCategory) {
        case "blouse" -> "Elegant";
        case "skirt" -> "Chic";
        case "dress" -> "Graceful";
        case "two-piece" -> "Sophisticated";
        case "short-padding" -> "Warm";
        case "long-padding" -> "Full-body warmth";
        case "lightweight-padding" -> "Light";
        case "boots" -> "Sturdy";
        case "sandal" -> "Breezy";
        case "sneakers" -> "Sporty";
        case "hoodie" -> "Casual";
        case "knit-sweater" -> "Snug";
        case "sweatshirt" -> "Relaxed";
        case "long-shirts" -> "Formal";
        case "short-shirts" -> "Cool";
        case "long-sleeve" -> "Comfy";
        case "short-sleeve" -> "Breathable";
        case "shorts" -> "Athletic";
        case "long" -> "Flowy";
        case "set-up" -> "Coordinated";
        case "cardigan" -> "Layered";
        case "coat" -> "Classic";
        case "jacket" -> "Stylish";
        case "vest" -> "Versatile";
        case "cap" -> "Trendy";
        case "socks" -> "Cozy";
        case "bag" -> "Fashionable";
        default -> "Unique";
    };
}

Chat GPT 4o 가 출시되고, 결제한 김에 상품을 수식하는 적당한 형용사를 붙여달라고 요청 했고
특정 형용사는 적절하지 않거나, 중복되는 형용사가 많았어서 제가 직접 수정했습니다. 

 
private ProductManagement createProductManagementV2(Product product, String imagePath, ProductColor color, List<Category> categories) {
        long additionalStock = 0;
        boolean isRestockAvailable = true;
        boolean isRestocked = false;
        boolean isSoldOut = false;
        long initialStock = random.nextInt(1000);
        long productStock = initialStock;

        String[] splitPath = imagePath.split("_");
        String category = splitPath[0];
        String subCategory = splitPath[1];

        // Subcategory matching using the categories list
        Category matchedCategory = null;
        for (Category cat : categories) {
            if (cat.getName().equals(subCategory)) {
                matchedCategory = cat;
                break;
            }
        }

        // If no matching category found, return null or throw an exception
        if(matchedCategory == null) {
            return null; // or throw exception
        }

        // Random size selection
        Size size = Size.values()[random.nextInt(Size.values().length)];

        // Preset color selection
//        ProductColor productColor = new ProductColor(color);

        return new ProductManagement(initialStock, additionalStock, matchedCategory, product, productStock, size, color, isRestockAvailable, isRestocked, isSoldOut);
    }

    public ProductColor getRandomColor() {
        List<ProductColor> colors = productColorRepository.findAll();
        int randomIndex = new Random().nextInt(colors.size());
        return colors.get(randomIndex);
    }

여기서 Size 는 상품 사이즈로, enum 타입입니다.

package PU.pushop.productManagement.entity.enums;

public enum Size {
    XSMALL("X-Small"),
    SMALL("Small"),
    MEDIUM("Medium"),
    LARGE("Large"),
    XLARGE("X-Large"),
    FREE("Free");

    private String description;

    Size(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

 사이즈에 대해서도, 상품의 카테고리가 엄청 다양하다면 테이블화해서 확장할 수 있지만

현재 쇼핑몰은 의류 쇼핑몰로서 목적이 뚜렷하고, 추후 확장까지 고려한 서비스가 아니기에

테이블화 해서 확장까지 고려하지는 않았습니다.


MySQL Workbench 에서 확인한 더미데이터

discount_rate is_discount is_recommend price created_at product_id updated_at wishlist_count manufacturer product_info product_name product_type
30 1 0 200 2024-07-12 20:09:18 1 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a unisex product for bag [Stylish Stitches Ltd] UNISEX Fashionable bag [30% 할인특가] UNISEX
40 1 0 400 2024-07-12 20:09:18 2 2024-07-12 20:09:18 NULL Urban Garments Manufacturing This is a unisex product for cardigan [Urban Garments Manufacturing] UNISEX Layered cardigan [40% 할인특가] UNISEX
NULL 0 1 400 2024-07-12 20:09:18 3 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a unisex product for sneakers [TrendSet Clothing Co] UNISEX Sporty sneakers UNISEX
NULL 0 0 400 2024-07-12 20:09:18 4 2024-07-12 20:09:18 NULL FashionThreads Inc This is a unisex product for bag [FashionThreads Inc] UNISEX Fashionable bag UNISEX
10 1 1 200 2024-07-12 20:09:18 5 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a man product for coat [TrendSet Clothing Co] MAN Classic coat [10% 할인특가] MAN
NULL 0 1 300 2024-07-12 20:09:18 6 2024-07-12 20:09:18 NULL ChicWear Productions This is a unisex product for sneakers [ChicWear Productions] UNISEX Sporty sneakers UNISEX
10 1 0 400 2024-07-12 20:09:18 7 2024-07-12 20:09:18 NULL Urban Garments Manufacturing This is a unisex product for cap [Urban Garments Manufacturing] UNISEX Trendy cap [10% 할인특가] UNISEX
NULL 0 1 200 2024-07-12 20:09:18 8 2024-07-12 20:09:18 NULL FashionThreads Inc This is a man product for coat [FashionThreads Inc] MAN Classic coat MAN
NULL 0 1 200 2024-07-12 20:09:18 9 2024-07-12 20:09:18 NULL ChicWear Productions This is a woman product for blouse [ChicWear Productions] WOMAN Elegant blouse WOMAN
NULL 0 1 200 2024-07-12 20:09:18 10 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a unisex product for cap [Stylish Stitches Ltd] UNISEX Trendy cap UNISEX
NULL 0 1 200 2024-07-12 20:09:18 11 2024-07-12 20:09:18 NULL FashionThreads Inc This is a unisex product for jacket [FashionThreads Inc] UNISEX Stylish jacket UNISEX
NULL 0 0 400 2024-07-12 20:09:18 12 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a woman product for blouse [Stylish Stitches Ltd] WOMAN Elegant blouse WOMAN
NULL 0 1 200 2024-07-12 20:09:18 13 2024-07-12 20:09:18 NULL Urban Garments Manufacturing This is a unisex product for socks [Urban Garments Manufacturing] UNISEX Cozy socks UNISEX
40 1 1 300 2024-07-12 20:09:18 14 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a unisex product for jacket [Elegant Fabrics Ltd] UNISEX Stylish jacket [40% 할인특가] UNISEX
50 1 0 400 2024-07-12 20:09:18 15 2024-07-12 20:09:18 NULL Elite Apparel Co This is a unisex product for hoodie [Elite Apparel Co] UNISEX Casual hoodie [50% 할인특가] UNISEX
30 1 1 300 2024-07-12 20:09:18 16 2024-07-12 20:09:18 NULL FashionThreads Inc This is a unisex product for socks [FashionThreads Inc] UNISEX Cozy socks [30% 할인특가] UNISEX
50 1 1 300 2024-07-12 20:09:18 17 2024-07-12 20:09:18 NULL Urban Garments Manufacturing This is a unisex product for lightweight-padding [Urban Garments Manufacturing] UNISEX Light lightweight-padding [50% 할인특가] UNISEX
NULL 0 0 400 2024-07-12 20:09:18 18 2024-07-12 20:09:18 NULL FashionThreads Inc This is a unisex product for hoodie [FashionThreads Inc] UNISEX Casual hoodie UNISEX
NULL 0 0 400 2024-07-12 20:09:18 19 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a man product for long [Stylish Stitches Ltd] MAN Flowy long MAN
30 1 1 200 2024-07-12 20:09:18 20 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a unisex product for lightweight-padding [Elegant Fabrics Ltd] UNISEX Light lightweight-padding [30% 할인특가] UNISEX
NULL 0 0 200 2024-07-12 20:09:18 21 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a unisex product for knit-sweater [TrendSet Clothing Co] UNISEX Snug knit-sweater UNISEX
NULL 0 0 200 2024-07-12 20:09:18 22 2024-07-12 20:09:18 NULL ChicWear Productions This is a man product for long [ChicWear Productions] MAN Flowy long MAN
NULL 0 1 200 2024-07-12 20:09:18 23 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a unisex product for long-padding [TrendSet Clothing Co] UNISEX Full-body warmth long-padding UNISEX
NULL 0 0 200 2024-07-12 20:09:18 24 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a unisex product for knit-sweater [Stylish Stitches Ltd] UNISEX Snug knit-sweater UNISEX
NULL 0 1 400 2024-07-12 20:09:18 25 2024-07-12 20:09:18 NULL ChicWear Productions This is a unisex product for shorts [ChicWear Productions] UNISEX Athletic shorts UNISEX
NULL 0 0 400 2024-07-12 20:09:18 26 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a unisex product for long-padding [TrendSet Clothing Co] UNISEX Full-body warmth long-padding UNISEX
NULL 0 0 400 2024-07-12 20:09:18 27 2024-07-12 20:09:18 NULL FashionThreads Inc This is a unisex product for long-shirts [FashionThreads Inc] UNISEX Formal long-shirts UNISEX
30 1 1 200 2024-07-12 20:09:18 28 2024-07-12 20:09:18 NULL Urban Garments Manufacturing This is a unisex product for shorts [Urban Garments Manufacturing] UNISEX Athletic shorts [30% 할인특가] UNISEX
20 1 1 300 2024-07-12 20:09:18 29 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a man product for mustang [Stylish Stitches Ltd] MAN Unique mustang [20% 할인특가] MAN
10 1 0 200 2024-07-12 20:09:18 30 2024-07-12 20:09:18 NULL Elite Apparel Co This is a unisex product for long-shirts [Elite Apparel Co] UNISEX Formal long-shirts [10% 할인특가] UNISEX
NULL 0 1 200 2024-07-12 20:09:18 31 2024-07-12 20:09:18 NULL FashionThreads Inc This is a woman product for skirt [FashionThreads Inc] WOMAN Chic skirt WOMAN
NULL 0 0 300 2024-07-12 20:09:18 32 2024-07-12 20:09:18 NULL ChicWear Productions This is a man product for mustang [ChicWear Productions] MAN Unique mustang MAN
20 1 1 300 2024-07-12 20:09:18 33 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a unisex product for long-sleeve [Elegant Fabrics Ltd] UNISEX Comfy long-sleeve [20% 할인특가] UNISEX
50 1 0 300 2024-07-12 20:09:18 34 2024-07-12 20:09:18 NULL FashionThreads Inc This is a woman product for skirt [FashionThreads Inc] WOMAN Chic skirt [50% 할인특가] WOMAN
NULL 0 1 200 2024-07-12 20:09:18 35 2024-07-12 20:09:18 NULL Elite Apparel Co This is a woman product for short-padding [Elite Apparel Co] WOMAN Warm short-padding WOMAN
50 1 0 400 2024-07-12 20:09:18 36 2024-07-12 20:09:18 NULL ChicWear Productions This is a unisex product for long-sleeve [ChicWear Productions] UNISEX Comfy long-sleeve [50% 할인특가] UNISEX
NULL 0 0 400 2024-07-12 20:09:18 37 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a woman product for dress [TrendSet Clothing Co] WOMAN Graceful dress WOMAN
30 1 0 200 2024-07-12 20:09:18 38 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a woman product for short-padding [Elegant Fabrics Ltd] WOMAN Warm short-padding [30% 할인특가] WOMAN
30 1 1 200 2024-07-12 20:09:18 39 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a unisex product for short-shirts [Elegant Fabrics Ltd] UNISEX Cool short-shirts [30% 할인특가] UNISEX
NULL 0 1 200 2024-07-12 20:09:18 40 2024-07-12 20:09:18 NULL ChicWear Productions This is a woman product for dress [ChicWear Productions] WOMAN Graceful dress WOMAN
50 1 1 300 2024-07-12 20:09:18 41 2024-07-12 20:09:18 NULL Urban Garments Manufacturing This is a unisex product for vest [Urban Garments Manufacturing] UNISEX Versatile vest [50% 할인특가] UNISEX
NULL 0 1 200 2024-07-12 20:09:18 42 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a unisex product for short-shirts [Elegant Fabrics Ltd] UNISEX Cool short-shirts UNISEX
NULL 0 1 200 2024-07-12 20:09:18 43 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a man product for set-up [TrendSet Clothing Co] MAN Coordinated set-up MAN
NULL 0 1 200 2024-07-12 20:09:18 44 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a unisex product for vest [TrendSet Clothing Co] UNISEX Versatile vest UNISEX
NULL 0 0 200 2024-07-12 20:09:18 45 2024-07-12 20:09:18 NULL Elite Apparel Co This is a man product for short-sleeve [Elite Apparel Co] MAN Breathable short-sleeve MAN
40 1 1 300 2024-07-12 20:09:18 46 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a man product for set-up [TrendSet Clothing Co] MAN Coordinated set-up [40% 할인특가] MAN
10 1 0 300 2024-07-12 20:09:18 47 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a woman product for boots [Stylish Stitches Ltd] WOMAN Sturdy boots [10% 할인특가] WOMAN
NULL 0 0 400 2024-07-12 20:09:18 48 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a man product for short-sleeve [Elegant Fabrics Ltd] MAN Breathable short-sleeve MAN
NULL 0 0 400 2024-07-12 20:09:18 49 2024-07-12 20:09:18 NULL TrendSet Clothing Co This is a woman product for two-piece [TrendSet Clothing Co] WOMAN Sophisticated two-piece WOMAN
10 1 0 200 2024-07-12 20:09:18 50 2024-07-12 20:09:18 NULL Stylish Stitches Ltd This is a woman product for boots [Stylish Stitches Ltd] WOMAN Sturdy boots [10% 할인특가] WOMAN
NULL 0 1 400 2024-07-12 20:09:18 51 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a man product for sweatshirt [Elegant Fabrics Ltd] MAN Relaxed sweatshirt MAN
NULL 0 1 200 2024-07-12 20:09:18 52 2024-07-12 20:09:18 NULL Urban Garments Manufacturing This is a woman product for two-piece [Urban Garments Manufacturing] WOMAN Sophisticated two-piece WOMAN
10 1 1 400 2024-07-12 20:09:18 53 2024-07-12 20:09:18 NULL FashionThreads Inc This is a unisex product for sandal [FashionThreads Inc] UNISEX Breezy sandal [10% 할인특가] UNISEX
NULL 0 0 300 2024-07-12 20:09:18 54 2024-07-12 20:09:18 NULL Elite Apparel Co This is a man product for sweatshirt [Elite Apparel Co] MAN Relaxed sweatshirt MAN
NULL 0 1 200 2024-07-12 20:09:18 55 2024-07-12 20:09:18 NULL Elite Apparel Co This is a unisex product for cardigan [Elite Apparel Co] UNISEX Layered cardigan UNISEX
NULL 0 1 400 2024-07-12 20:09:18 56 2024-07-12 20:09:18 NULL Elegant Fabrics Ltd This is a unisex product for sandal [Elegant Fabrics Ltd] UNISEX Breezy sandal UNISEX

 

created_at product_id thumbnail_id image_path
2024-07-12 20:09:18 1 1 /uploads/thumbnails/accessories_bag_1.jpg
2024-07-12 20:09:18 2 2 /uploads/thumbnails/outer_cardigan_2.jpg
2024-07-12 20:09:18 3 3 /uploads/thumbnails/shoes_sneakers_1.jpg
2024-07-12 20:09:18 4 4 /uploads/thumbnails/accessories_bag_2.jpg
2024-07-12 20:09:18 5 5 /uploads/thumbnails/outer_coat_1.jpg
2024-07-12 20:09:18 6 6 /uploads/thumbnails/shoes_sneakers_2.jpg
2024-07-12 20:09:18 7 7 /uploads/thumbnails/accessories_cap_1.jpg
2024-07-12 20:09:18 8 8 /uploads/thumbnails/outer_coat_2.jpg
2024-07-12 20:09:18 9 9 /uploads/thumbnails/top_blouse_1.jpg
2024-07-12 20:09:18 10 10 /uploads/thumbnails/accessories_cap_2.jpg
2024-07-12 20:09:18 11 11 /uploads/thumbnails/outer_jacket_1.jpg
2024-07-12 20:09:18 12 12 /uploads/thumbnails/top_blouse_2.jpg
2024-07-12 20:09:18 13 13 /uploads/thumbnails/accessories_socks_1.jpg
2024-07-12 20:09:18 14 14 /uploads/thumbnails/outer_jacket_2.jpg
2024-07-12 20:09:18 15 15 /uploads/thumbnails/top_hoodie_1.jpg
2024-07-12 20:09:18 16 16 /uploads/thumbnails/accessories_socks_2.jpg
2024-07-12 20:09:18 17 17 /uploads/thumbnails/outer_lightweight-padding_1.jpg
2024-07-12 20:09:18 18 18 /uploads/thumbnails/top_hoodie_2.jpg
2024-07-12 20:09:18 19 19 /uploads/thumbnails/bottom_long_1.jpg
2024-07-12 20:09:18 20 20 /uploads/thumbnails/outer_lightweight-padding_2.jpg
2024-07-12 20:09:18 21 21 /uploads/thumbnails/top_knit-sweater_1.jpg
2024-07-12 20:09:18 22 22 /uploads/thumbnails/bottom_long_2.jpg
2024-07-12 20:09:18 23 23 /uploads/thumbnails/outer_long-padding_1.jpg
2024-07-12 20:09:18 24 24 /uploads/thumbnails/top_knit-sweater_2.jpg
2024-07-12 20:09:18 25 25 /uploads/thumbnails/bottom_shorts_1.jpg
2024-07-12 20:09:18 26 26 /uploads/thumbnails/outer_long-padding_2.jpg
2024-07-12 20:09:18 27 27 /uploads/thumbnails/top_long-shirts_1.jpg
2024-07-12 20:09:18 28 28 /uploads/thumbnails/bottom_shorts_2.jpg
2024-07-12 20:09:18 29 29 /uploads/thumbnails/outer_mustang_1.jpg
2024-07-12 20:09:18 30 30 /uploads/thumbnails/top_long-shirts_2.jpg
2024-07-12 20:09:18 31 31 /uploads/thumbnails/bottom_skirt_1.jpg
2024-07-12 20:09:18 32 32 /uploads/thumbnails/outer_mustang_2.jpg
2024-07-12 20:09:18 33 33 /uploads/thumbnails/top_long-sleeve_1.jpg
2024-07-12 20:09:18 34 34 /uploads/thumbnails/bottom_skirt_2.jpg
2024-07-12 20:09:18 35 35 /uploads/thumbnails/outer_short-padding_1.jpg
2024-07-12 20:09:18 36 36 /uploads/thumbnails/top_long-sleeve_2.jpg
2024-07-12 20:09:18 37 37 /uploads/thumbnails/dress&set_dress_1.jpg
2024-07-12 20:09:18 38 38 /uploads/thumbnails/outer_short-padding_2.jpg
2024-07-12 20:09:18 39 39 /uploads/thumbnails/top_short-shirts_1.jpg
2024-07-12 20:09:18 40 40 /uploads/thumbnails/dress&set_dress_2.jpg
2024-07-12 20:09:18 41 41 /uploads/thumbnails/outer_vest_1.jpg
2024-07-12 20:09:18 42 42 /uploads/thumbnails/top_short-shirts_2.jpg
2024-07-12 20:09:18 43 43 /uploads/thumbnails/dress&set_set-up_1.jpg
2024-07-12 20:09:18 44 44 /uploads/thumbnails/outer_vest_2.jpg
2024-07-12 20:09:18 45 45 /uploads/thumbnails/top_short-sleeve_1.jpg
2024-07-12 20:09:18 46 46 /uploads/thumbnails/dress&set_set-up_2.jpg
2024-07-12 20:09:18 47 47 /uploads/thumbnails/shoes_boots_1.jpg
2024-07-12 20:09:18 48 48 /uploads/thumbnails/top_short-sleeve_2.jpg
2024-07-12 20:09:18 49 49 /uploads/thumbnails/dress&set_two-piece_1.jpg
2024-07-12 20:09:18 50 50 /uploads/thumbnails/shoes_boots_2.jpg
2024-07-12 20:09:18 51 51 /uploads/thumbnails/top_sweatshirt_1.jpg
2024-07-12 20:09:18 52 52 /uploads/thumbnails/dress&set_two-piece_2.jpg
2024-07-12 20:09:18 53 53 /uploads/thumbnails/shoes_sandal_1.jpg
2024-07-12 20:09:18 54 54 /uploads/thumbnails/top_sweatshirt_2.jpg
2024-07-12 20:09:18 55 55 /uploads/thumbnails/outer_cardigan_1.jpg
2024-07-12 20:09:18 56 56 /uploads/thumbnails/shoes_sandal_2.jpg
category_id depth parent name
1 0 NULL top
2 1 1 blouse
3 1 1 hoodie
4 1 1 knit-sweater
5 1 1 long-shirts
6 1 1 long-sleeve
7 1 1 short-shirts
8 1 1 short-sleeve
9 1 1 sweatshirt
10 0 NULL bottom
11 1 10 long
12 1 10 shorts
13 1 10 skirt
14 0 NULL dress&set
15 1 14 dress
16 1 14 set-up
17 1 14 two-piece
18 0 NULL outer
19 1 18 cardigan
20 1 18 coat
21 1 18 jacket
22 1 18 lightweight-padding
23 1 18 long-padding
24 1 18 mustang
25 1 18 short-padding
26 1 18 vest
27 0 NULL shoes
28 1 27 boots
29 1 27 sandal
30 1 27 sneakers
31 0 NULL accessories
32 1 31 bag
33 1 31 cap
34 1 31 socks
color_id color
13 Beige
8 Black
5 Blue
10 Gray
4 Green
12 Ivory
6 Navy
2 Orange
11 Pink
7 Purple
14 Rainbow
1 Red
9 White
3 Yellow
isRestockAvailable isRestocked isSoldOut additional_stock category_id color_id initial_stock inventory_id product_id product_stock size
1 0 0 0 32 2 765 1 1 765 XLARGE
1 0 0 0 32 10 283 2 1 283 FREE
1 0 0 0 32 13 635 3 1 635 LARGE
1 0 0 0 19 2 912 4 2 912 XSMALL
1 0 0 0 19 10 146 5 2 146 XSMALL
1 0 0 0 19 13 198 6 2 198 LARGE
1 0 0 0 30 2 798 7 3 798 SMALL
1 0 0 0 30 10 149 8 3 149 MEDIUM
1 0 0 0 30 13 571 9 3 571 FREE
1 0 0 0 32 2 912 10 4 912 LARGE
1 0 0 0 32 10 150 11 4 150 XSMALL
1 0 0 0 32 13 368 12 4 368 LARGE
1 0 0 0 20 2 591 13 5 591 XSMALL
1 0 0 0 20 10 911 14 5 911 FREE
1 0 0 0 20 13 765 15 5 765 XLARGE
1 0 0 0 30 2 404 16 6 404 FREE
1 0 0 0 30 10 550 17 6 550 XLARGE
1 0 0 0 30 13 654 18 6 654 LARGE
1 0 0 0 33 2 553 19 7 553 MEDIUM
1 0 0 0 33 10 334 20 7 334 SMALL
1 0 0 0 33 13 619 21 7 619 SMALL
1 0 0 0 20 2 565 22 8 565 FREE
1 0 0 0 20 10 586 23 8 586 SMALL
1 0 0 0 20 13 959 24 8 959 MEDIUM
1 0 0 0 2 2 192 25 9 192 FREE
1 0 0 0 2 10 835 26 9 835 XLARGE
1 0 0 0 2 13 416 27 9 416 SMALL
1 0 0 0 33 2 145 28 10 145 LARGE
1 0 0 0 33 10 222 29 10 222 XLARGE
1 0 0 0 33 13 863 30 10 863 SMALL
1 0 0 0 21 2 438 31 11 438 MEDIUM
1 0 0 0 21 10 151 32 11 151 SMALL
1 0 0 0 21 13 997 33 11 997 XLARGE
1 0 0 0 2 2 488 34 12 488 XLARGE
1 0 0 0 2 10 627 35 12 627 SMALL
1 0 0 0 2 13 799 36 12 799 XLARGE
1 0 0 0 34 2 797 37 13 797 LARGE
1 0 0 0 34 10 433 38 13 433 XLARGE
1 0 0 0 34 13 958 39 13 958 MEDIUM
1 0 0 0 21 2 256 40 14 256 XSMALL
1 0 0 0 21 10 365 41 14 365 SMALL
1 0 0 0 21 13 993 42 14 993 MEDIUM
1 0 0 0 3 2 783 43 15 783 XSMALL
1 0 0 0 3 10 550 44 15 550 XLARGE
1 0 0 0 3 13 354 45 15 354 FREE
1 0 0 0 34 2 12 46 16 12 MEDIUM
1 0 0 0 34 10 667 47 16 667 LARGE
1 0 0 0 34 13 443 48 16 443 FREE
1 0 0 0 22 2 84 49 17 84 FREE
1 0 0 0 22 10 421 50 17 421 XLARGE
1 0 0 0 22 13 398 51 17 398 MEDIUM
1 0 0 0 3 2 605 52 18 605 LARGE
1 0 0 0 3 10 678 53 18 678 LARGE
1 0 0 0 3 13 214 54 18 214 FREE
1 0 0 0 11 2 671 55 19 671 SMALL
1 0 0 0 11 10 61 56 19 61 XSMALL
1 0 0 0 11 13 997 57 19 997 SMALL
1 0 0 0 22 2 300 58 20 300 XSMALL
1 0 0 0 22 10 793 59 20 793 FREE
1 0 0 0 22 13 147 60 20 147 FREE
1 0 0 0 4 2 326 61 21 326 LARGE
1 0 0 0 4 10 61 62 21 61 XLARGE
1 0 0 0 4 13 254 63 21 254 XLARGE
1 0 0 0 11 2 941 64 22 941 LARGE
1 0 0 0 11 10 833 65 22 833 XLARGE
1 0 0 0 11 13 979 66 22 979 MEDIUM
1 0 0 0 23 2 116 67 23 116 XSMALL
1 0 0 0 23 10 822 68 23 822 LARGE
1 0 0 0 23 13 650 69 23 650 XLARGE
1 0 0 0 4 2 695 70 24 695 SMALL
1 0 0 0 4 10 754 71 24 754 XSMALL
1 0 0 0 4 13 680 72 24 680 XSMALL
1 0 0 0 12 2 76 73 25 76 SMALL
1 0 0 0 12 10 280 74 25 280 LARGE
1 0 0 0 12 13 777 75 25 777 XLARGE
1 0 0 0 23 2 925 76 26 925 XLARGE
1 0 0 0 23 10 238 77 26 238 XLARGE
1 0 0 0 23 13 604 78 26 604 MEDIUM
1 0 0 0 5 2 468 79 27 468 MEDIUM
1 0 0 0 5 10 551 80 27 551 MEDIUM
1 0 0 0 5 13 408 81 27 408 SMALL
1 0 0 0 12 2 955 82 28 955 LARGE
1 0 0 0 12 10 650 83 28 650 MEDIUM
1 0 0 0 12 13 645 84 28 645 MEDIUM
1 0 0 0 24 2 292 85 29 292 XLARGE
1 0 0 0 24 10 497 86 29 497 LARGE
1 0 0 0 24 13 945 87 29 945 XLARGE
1 0 0 0 5 2 327 88 30 327 LARGE
1 0 0 0 5 10 127 89 30 127 SMALL
1 0 0 0 5 13 747 90 30 747 MEDIUM
1 0 0 0 13 2 170 91 31 170 SMALL
1 0 0 0 13 10 326 92 31 326 XSMALL
1 0 0 0 13 13 279 93 31 279 MEDIUM
1 0 0 0 24 2 646 94 32 646 SMALL
1 0 0 0 24 10 769 95 32 769 SMALL
1 0 0 0 24 13 479 96 32 479 XLARGE
1 0 0 0 6 2 276 97 33 276 XLARGE
1 0 0 0 6 10 100 98 33 100 XLARGE
1 0 0 0 6 13 356 99 33 356 XLARGE
1 0 0 0 13 2 327 100 34 327 MEDIUM
1 0 0 0 13 10 328 101 34 328 LARGE
1 0 0 0 13 13 568 102 34 568 MEDIUM
1 0 0 0 25 2 529 103 35 529 SMALL
1 0 0 0 25 10 637 104 35 637 SMALL
1 0 0 0 25 13 985 105 35 985 XLARGE
1 0 0 0 6 2 702 106 36 702 MEDIUM
1 0 0 0 6 10 834 107 36 834 FREE
1 0 0 0 6 13 428 108 36 428 SMALL
1 0 0 0 15 2 876 109 37 876 SMALL
1 0 0 0 15 10 302 110 37 302 SMALL
1 0 0 0 15 13 10 111 37 10 FREE
1 0 0 0 25 2 864 112 38 864 MEDIUM
1 0 0 0 25 10 881 113 38 881 SMALL
1 0 0 0 25 13 96 114 38 96 LARGE
1 0 0 0 7 2 14 115 39 14 XLARGE
1 0 0 0 7 10 286 116 39 286 LARGE
1 0 0 0 7 13 499 117 39 499 XSMALL
1 0 0 0 15 2 727 118 40 727 LARGE
1 0 0 0 15 10 294 119 40 294 LARGE
1 0 0 0 15 13 302 120 40 302 LARGE
1 0 0 0 26 2 70 121 41 70 XLARGE
1 0 0 0 26 10 800 122 41 800 LARGE
1 0 0 0 26 13 35 123 41 35 LARGE
1 0 0 0 7 2 786 124 42 786 LARGE
1 0 0 0 7 10 977 125 42 977 LARGE
1 0 0 0 7 13 113 126 42 113 SMALL
1 0 0 0 16 2 632 127 43 632 XSMALL
1 0 0 0 16 10 558 128 43 558 XSMALL
1 0 0 0 16 13 316 129 43 316 MEDIUM
1 0 0 0 26 2 364 130 44 364 FREE
1 0 0 0 26 10 140 131 44 140 FREE
1 0 0 0 26 13 511 132 44 511 FREE
1 0 0 0 8 2 936 133 45 936 MEDIUM
1 0 0 0 8 10 139 134 45 139 LARGE
1 0 0 0 8 13 660 135 45 660 XSMALL
1 0 0 0 16 2 30 136 46 30 XSMALL
1 0 0 0 16 10 907 137 46 907 XLARGE
1 0 0 0 16 13 891 138 46 891 XLARGE
1 0 0 0 28 2 626 139 47 626 LARGE
1 0 0 0 28 10 20 140 47 20 XSMALL
1 0 0 0 28 13 43 141 47 43 SMALL
1 0 0 0 8 2 251 142 48 251 FREE
1 0 0 0 8 10 754 143 48 754 FREE
1 0 0 0 8 13 141 144 48 141 MEDIUM
1 0 0 0 17 2 800 145 49 800 FREE
1 0 0 0 17 10 700 146 49 700 XLARGE
1 0 0 0 17 13 121 147 49 121 XSMALL
1 0 0 0 28 2 479 148 50 479 XSMALL
1 0 0 0 28 10 996 149 50 996 FREE
1 0 0 0 28 13 16 150 50 16 LARGE
1 0 0 0 9 2 879 151 51 879 FREE
1 0 0 0 9 10 842 152 51 842 MEDIUM
1 0 0 0 9 13 676 153 51 676 LARGE
1 0 0 0 17 2 724 154 52 724 LARGE
1 0 0 0 17 10 643 155 52 643 XSMALL
1 0 0 0 17 13 590 156 52 590 XSMALL
1 0 0 0 29 2 221 157 53 221 LARGE
1 0 0 0 29 10 520 158 53 520 XSMALL
1 0 0 0 29 13 299 159 53 299 FREE
1 0 0 0 9 2 834 160 54 834 XLARGE
1 0 0 0 9 10 401 161 54 401 FREE
1 0 0 0 9 13 139 162 54 139 SMALL
1 0 0 0 19 2 99 163 55 99 FREE
1 0 0 0 19 10 953 164 55 953 XSMALL
1 0 0 0 19 13 114 165 55 114 FREE
1 0 0 0 29 2 473 166 56 473 LARGE
1 0 0 0 29 10 386 167 56 386 SMALL
1 0 0 0 29 13 284 168 56 284 FREE

지금부터는, 각 유틸 클래스의 전체 코드입니다. 코드를 참고하실 수 있게 첨부해두겠습니다. 
이것으로 스프링 부트에서 ApplicationRunner 를 사용한 더미데이터 생성에 대한 포스팅을 마치겠습니다.
감사합니다.

package PU.pushop.global.dummydata.util;

import PU.pushop.product.entity.Product;
import PU.pushop.product.entity.enums.ProductType;
import PU.pushop.product.repository.ProductRepositoryV1;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * The ProductDataUtil class is responsible for generating and saving product data. It uses the ProductRepositoryV1
 * interface to save each product to the database. The generated product data is based on the given count parameter.
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ProductDataUtil {

    private final ProductRepositoryV1 productRepository;

    public static final String PRODUCT_NAME_TEMPLATE = "Product %d";
    public static final String PRODUCT_INFO_TEMPLATE = "This is a %s product";
    public static final String MANUFACTURER_NAME_TEMPLATE = "Manufacturer %d";

    public List<Product> generateProductDataWithImages(List<String> imagePaths) {
        return imagePaths.stream()
                .map(this::createProductFromImagePath)
                .map(this::saveProduct)
                .collect(Collectors.toList());
    }


    private Product createProductFromImagePath(String imagePath) {
        String[] splitPath = imagePath.split("_");
        String category = splitPath[0];
        String subCategory = splitPath[1];

        Random rand = new Random();

        // 제조업체 . 실제 존재하지 않습니다.
        String[] manufacturers = {
                "FashionThreads Inc",
                "Elite Apparel Co",
                "Stylish Stitches Ltd",
                "Urban Garments Manufacturing",
                "ChicWear Productions",
                "TrendSet Clothing Co",
                "Elegant Fabrics Ltd"
        };
        // 가격을 100, 200, 300, 400, 500 중에서 랜덤하게 select.
        int[] prices = {200, 300, 400};
        int[] discountRates = {10, 20, 30, 40, 50};

        int price = prices[rand.nextInt(prices.length)];
        String manufacturer = manufacturers[rand.nextInt(manufacturers.length)];
        ProductType productType = getProductType(subCategory);

        // isDiscount 여부에 따라, discountRate 를 정해주도록 [24.06.03]
        boolean isDiscount = rand.nextBoolean(); // 할인 여부
        Integer discountRate;
        if (isDiscount) {
            discountRate = discountRates[rand.nextInt(discountRates.length)];
        } else {
            discountRate = null;
        }
        boolean isRecommend = rand.nextBoolean(); // 추천 상품 여부

        String productName = buildProductName(manufacturer, productType, subCategory, discountRate);
        String productInfo = "This is a " + productType.toString().toLowerCase() + " product for " + subCategory;

        // You might want to set imagePath to your product here if you have such field in your Product entity
        return new Product(productName, productType, price, productInfo, manufacturer, isDiscount, discountRate, isRecommend);
    }

    private ProductType getProductType(String subCategory) {
        return switch (subCategory) {
            case "blouse", "skirt", "dress", "two-piece", "short-padding", "boots" -> ProductType.WOMAN;
            case "hoodie", "knit-sweater", "long-shirts", "long-sleeve", "short-shirts",
                  "shorts", "cardigan", "jacket", "lightweight-padding", "long-padding",
                 "vest", "sandal", "sneakers", "bag", "cap", "socks" -> ProductType.UNISEX;
            default -> ProductType.MAN;
        };
    }

    private String buildProductName(String manufacturer, ProductType productType, String subCategory, Integer discountRate) {
        String adjective = getAdjectiveForSubCategory(subCategory);
        String discountText = (discountRate != null) ? " [" + discountRate + "% 할인특가]" : "";
        return String.format("[%s] %s %s %s%s", manufacturer, productType, adjective, subCategory, discountText);
    }

    private String getAdjectiveForSubCategory(String subCategory) {
        return switch (subCategory) {
            case "blouse" -> "Elegant";
            case "skirt" -> "Chic";
            case "dress" -> "Graceful";
            case "two-piece" -> "Sophisticated";
            case "short-padding" -> "Warm";
            case "long-padding" -> "Full-body warmth";
            case "lightweight-padding" -> "Light";
            case "boots" -> "Sturdy";
            case "sandal" -> "Breezy";
            case "sneakers" -> "Sporty";
            case "hoodie" -> "Casual";
            case "knit-sweater" -> "Snug";
            case "sweatshirt" -> "Relaxed";
            case "long-shirts" -> "Formal";
            case "short-shirts" -> "Cool";
            case "long-sleeve" -> "Comfy";
            case "short-sleeve" -> "Breathable";
            case "shorts" -> "Athletic";
            case "long" -> "Flowy";
            case "set-up" -> "Coordinated";
            case "cardigan" -> "Layered";
            case "coat" -> "Classic";
            case "jacket" -> "Stylish";
            case "vest" -> "Versatile";
            case "cap" -> "Trendy";
            case "socks" -> "Cozy";
            case "bag" -> "Fashionable";
            default -> "Unique";
        };
    }


    // 단순히 DB 에 저장하는 로직
    private Product saveProduct(Product product) {
        try {
            return productRepository.save(product);
        } catch (DataIntegrityViolationException ex) {
            if (ex.getCause() instanceof ConstraintViolationException constraintException) {
                log.error("Constraint violation for Product: " + product.toString(), constraintException.getSQLException());
            }
            throw ex;
        }
    }

    private String buildProductInfo(ProductType productType) {
        return String.format(PRODUCT_INFO_TEMPLATE, productType.toString().toLowerCase());
    }

    private String buildManufacturerName(int index) {
        return String.format(MANUFACTURER_NAME_TEMPLATE, index);
    }

}

 

package PU.pushop.global.dummydata.util;

import PU.pushop.product.entity.Product;
import PU.pushop.product.repository.ProductRepositoryV1;
import PU.pushop.productThumbnail.entity.ProductThumbnail;
import PU.pushop.productThumbnail.repository.ProductThumbnailRepositoryV1;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.IntStream;


/**
 * Utility class for generating and saving product thumbnail data.
 */
@Component
@RequiredArgsConstructor
public class ProductThumbnailDataUtil {

    private final ProductRepositoryV1 productRepository;
    private final ProductThumbnailRepositoryV1 productThumbnailRepository;

    public void generateProductThumbnailDataV1(int count) {
        String[] images = {
                "accessories_bag_1.jpg", "outer_cardigan_2.jpg", "shoes_sneakers_1.jpg",
                "accessories_bag_2.jpg", "outer_coat_1.jpg", "shoes_sneakers_2.jpg",
                "accessories_cap_1.jpg", "outer_coat_2.jpg", "top_blouse_1.jpg",
                "accessories_cap_2.jpg", "outer_jacket_1.jpg", "top_blouse_2.jpg",
                "accessories_socks_1.jpg", "outer_jacket_2.jpg", "top_hoodie_1.jpg",
                "accessories_socks_2.jpg", "outer_lightweight-padding_1.jpg","top_hoodie_2.jpg",
                "bottom_long_1.jpg", "outer_lightweight-padding_2.jpg", "top_knit-sweater_1.jpg",
                "bottom_long_2.jpg", "outer_long-padding_1.jpg", "top_knit-sweater_2.jpg",
                "bottom_shorts_1.jpg", "outer_long-padding_2.jpg", "top_long-shirts_1.jpg",
                "bottom_shorts_2.jpg", "outer_mustang_1.jpg", "top_long-shirts_2.jpg",
                "bottom_skirt_1.jpg", "outer_mustang_2.jpg", "top_long-sleeve_1.jpg",
                "bottom_skirt_2.jpg", "outer_short-padding_1.jpg", "top_long-sleeve_2.jpg",
                "dress&set_dress_1.jpg", "outer_short-padding_2.jpg", "top_short-shirts_1.jpg",
                "dress&set_dress_2.jpg", "outer_vest_1.jpg", "top_short-shirts_2.jpg",
                "dress&set_set-up_1.jpg", "outer_vest_2.jpg", "top_short-sleeve_1.jpg",
                "dress&set_set-up_2.jpg", "shoes_boots_1.jpg", "top_short-sleeve_2.jpg",
                "dress&set_two-piece_1.jpg", "shoes_boots_2.jpg", "top_sweatshirt_1.jpg",
                "dress&set_two-piece_2.jpg", "shoes_sandal_1.jpg", "top_sweatshirt_2.jpg",
                "outer_cardigan_1.jpg", "shoes_sandal_2.jpg"
        };

        IntStream.rangeClosed(1, count).forEach(i -> {
            // Get image file name from array
            String imageFile = images[i % images.length];

            // Split file name into parts
            String[] parts = imageFile.split("_");

            // 이미지 경로 생성
            String imagePath = String.format("/static/uploads/thumbnails/%s", imageFile);

            // 상품 조회
            Product product = productRepository.findById((long) i)
                    .orElseThrow(() -> new NoSuchElementException("해당 상품이 존재하지 않습니다."));

            // 썸네일 생성 및 저장
            ProductThumbnail productThumbnail = new ProductThumbnail(product, imagePath);
            productThumbnailRepository.save(productThumbnail);
        });
    }

    public void generateProductThumbnailDataV2(List<String> imagePaths) {
        IntStream.range(0, imagePaths.size()).forEach(i -> {
            // 이미지 경로 생성
            String imagePath = String.format("/uploads/thumbnails/%s", imagePaths.get(i));

            // 상품 조회 - 필요에 따라 생성된 상품의 식별자를 알고 있는 경우 수정 가능
            Product product = productRepository.findById((long) (i+1))
                    .orElseThrow(() -> new NoSuchElementException("해당 상품이 존재하지 않습니다."));

            // 썸네일 생성 및 저장
            ProductThumbnail productThumbnail = new ProductThumbnail(product, imagePath);
            productThumbnailRepository.save(productThumbnail);
        });
    }

    public void generateProductThumbnailDataV3(List<Product> products, List<String> imagePaths) {
        if(imagePaths.size() != products.size()) {
            throw new IllegalArgumentException("The number of products and image paths should be equal");
        }

        for (int i = 0; i < products.size(); i++) {
            // 이미지 경로 생성
            String imagePath = String.format("/uploads/thumbnails/%s", imagePaths.get(i));
            // 상품 추출
            Product product = products.get(i);
            // 썸네일 생성 및 저장
            ProductThumbnail productThumbnail = new ProductThumbnail(product, imagePath);
            productThumbnailRepository.save(productThumbnail);
        }
    }
}

 

package PU.pushop.global.dummydata.util;

import PU.pushop.category.entity.Category;
import PU.pushop.category.repository.CategoryRepository;
import PU.pushop.category.service.CategoryServiceV1;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


@Component
@RequiredArgsConstructor
public class CategoryDataUtil {

    private final CategoryRepository categoryRepository;
    private final CategoryServiceV1 categoryService;

    public List<Category> generateCategoryData() {
        List<Category> categories = new ArrayList<>();

        // top, bottom, dress&set, outer, shoes, accessories 순서
        // "상의"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
        List<Category> topsChildren = new ArrayList<>();
        Category topParentCategory = createAndSaveParentCategory(1L, "top", new ArrayList<>());
        Category blouse = createAndSaveChildCategoryV2(2L, "blouse", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(blouse);
        Category hoodie = createAndSaveChildCategoryV2(3L, "hoodie", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(hoodie);
        Category knitSweater = createAndSaveChildCategoryV2(4L, "knit-sweater", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(knitSweater);
        Category longShirts = createAndSaveChildCategoryV2(5L, "long-shirts", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(longShirts);
        Category longSleeve = createAndSaveChildCategoryV2(6L, "long-sleeve", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(longSleeve);
        Category shortShirts = createAndSaveChildCategoryV2(7L, "short-shirts", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(shortShirts);
        Category shortSleeve = createAndSaveChildCategoryV2(8L, "short-sleeve", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(shortSleeve);
        Category sweatshirt = createAndSaveChildCategoryV2(9L, "sweatshirt", topParentCategory.getCategoryId(), new ArrayList<>());
        topsChildren.add(sweatshirt);
        topParentCategory.setChildren(topsChildren);

        // "하의"에 하위 카테고리 생성
        List<Category> bottomChildren = new ArrayList<>();
        Category bottomParentCategory = createAndSaveParentCategory(10L, "bottom", new ArrayList<>());
        Category longBottom = createAndSaveChildCategoryV2(11L, "long", bottomParentCategory.getCategoryId(), new ArrayList<>());
        bottomChildren.add(longBottom);
        Category shorts = createAndSaveChildCategoryV2(12L, "shorts", bottomParentCategory.getCategoryId(), new ArrayList<>());
        bottomChildren.add(shorts);
        Category skirt = createAndSaveChildCategoryV2(13L, "skirt", bottomParentCategory.getCategoryId(), new ArrayList<>());
        bottomChildren.add(skirt);
        bottomParentCategory.setChildren(bottomChildren);

        // "dress&set"에 하위 카테고리 생성
        List<Category> dressChildren = new ArrayList<>();
        Category dressParentCategory = createAndSaveParentCategory(14L, "dress&set", new ArrayList<>());
        Category dress = createAndSaveChildCategoryV2(15L, "dress", dressParentCategory.getCategoryId(), new ArrayList<>());
        dressChildren.add(dress);
        Category setUp = createAndSaveChildCategoryV2(16L, "set-up", dressParentCategory.getCategoryId(), new ArrayList<>());
        dressChildren.add(setUp);
        Category twoPiece = createAndSaveChildCategoryV2(17L, "two-piece", dressParentCategory.getCategoryId(), new ArrayList<>());
        dressChildren.add(twoPiece);
        dressParentCategory.setChildren(dressChildren);

        // "아우터"에 대한 하위 카테고리 생성 후, 하위 카테고리로 다음을 추가
        List<Category> outerChildren = new ArrayList<>();
        Category outerParentCategory = createAndSaveParentCategory(18L, "outer", new ArrayList<>());
        Category cardigan = createAndSaveChildCategoryV2(19L, "cardigan", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(cardigan);
        Category coat = createAndSaveChildCategoryV2(20L, "coat", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(coat);
        Category jacket = createAndSaveChildCategoryV2(21L, "jacket", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(jacket);
        Category lightweightPadding = createAndSaveChildCategoryV2(22L, "lightweight-padding", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(lightweightPadding);
        Category longPadding = createAndSaveChildCategoryV2(23L, "long-padding", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(longPadding);
        Category mustang = createAndSaveChildCategoryV2(24L, "mustang", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(mustang);
        Category shortPadding = createAndSaveChildCategoryV2(25L, "short-padding", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(shortPadding);
        Category vest = createAndSaveChildCategoryV2(26L, "vest", outerParentCategory.getCategoryId(), new ArrayList<>());
        outerChildren.add(vest);
        outerParentCategory.setChildren(outerChildren);

        // "신발"에 대한 하위 카테고리 생성 후, 하위 카테고리로 다음을 추가
        List<Category> shoesChildren = new ArrayList<>();
        Category shoesParentCategory = createAndSaveParentCategory(27L, "shoes", new ArrayList<>());
        Category boots = createAndSaveChildCategoryV2(28L, "boots", shoesParentCategory.getCategoryId(), new ArrayList<>());
        shoesChildren.add(boots);
        Category sandal = createAndSaveChildCategoryV2(29L, "sandal", shoesParentCategory.getCategoryId(), new ArrayList<>());
        shoesChildren.add(sandal);
        Category sneakers = createAndSaveChildCategoryV2(30L, "sneakers", shoesParentCategory.getCategoryId(), new ArrayList<>());
        shoesChildren.add(sneakers);
        shoesParentCategory.setChildren(shoesChildren);

        // "악세사리"에 대한 하위 카테고리 생성 후, 하위 카테고리로 다음을 추가
        List<Category> accessoryChildren = new ArrayList<>();
        Category accessoryParentCategory = createAndSaveParentCategory(31L, "accessories", new ArrayList<>());
        Category bag = createAndSaveChildCategoryV2(32L, "bag", accessoryParentCategory.getCategoryId(), new ArrayList<>());
        accessoryChildren.add(bag);
        Category cap = createAndSaveChildCategoryV2(33L, "cap", accessoryParentCategory.getCategoryId(), new ArrayList<>());
        accessoryChildren.add(cap);
        Category socks = createAndSaveChildCategoryV2(34L, "socks", accessoryParentCategory.getCategoryId(), new ArrayList<>());
        accessoryChildren.add(socks);
        accessoryParentCategory.setChildren(accessoryChildren);

        // Add constructed parent categories to categories list
        categories.addAll(topParentCategory.getChildren());
        categories.addAll(bottomParentCategory.getChildren());
        categories.addAll(dressParentCategory.getChildren());
        categories.addAll(outerParentCategory.getChildren());
        categories.addAll(shoesParentCategory.getChildren());
        categories.addAll(accessoryParentCategory.getChildren());

        System.out.println("categories = " + categories);
        return categories;
    }


    private Category createAndSaveParentCategory(Long categoryId, String name, List<Category> children) {
        // DB 에 이미 존재하는 category Id 인지 확인한다.
        Optional<Category> optionalCategory = categoryRepository.findByCategoryId(categoryId);

        if (optionalCategory.isPresent()) {
            return optionalCategory.get();
        } else {
            Category category = Category.createCategoryDummyData(categoryId, name, 0L, children);
            children.forEach(child -> child.setParent(category));
            category.setChildren(children);
            categoryService.createCategory(category, null);
            return category;
        }
    }

    protected Category createAndSaveChildCategoryV2(Long categoryId, String name, Long parentId, List<Category> children) {
        // DB에 이미 존재하는 category Id인지 확인한다.
        Optional<Category> optionalCategory = categoryRepository.findByCategoryId(categoryId);

        if(optionalCategory.isPresent()){
            // If category already exists, return it
            return optionalCategory.get();
        } else {
            Category category = Category.createChildCategory(categoryId, name, 1L, children);

            if (parentId != null) {
                Category parentCategory = categoryRepository.findById(parentId).orElseThrow(() ->
                        new RuntimeException("부모 카테고리를 찾을 수 없습니다. ID: " + parentId));
                category.setParent(parentCategory);
            }

            categoryService.createCategory(category, parentId);
            return category;
        }
    }


    /**
     * 2024.04.23 김성우
     * 부모 카테고리 생성 후, 자식 카테고리를 생성하지 않아
     * 부모 카테고리 id를 찾을 수 없어 RuntimeException 발생
     */
    public void generateCategoryDataV1() {
        // "상의"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
        List<Category> TopChildren = new ArrayList<>();
        TopChildren.add(createAndSaveChildCategoryV2(2L, "후드", 1L, new ArrayList<>()));
        TopChildren.add(createAndSaveChildCategoryV2(3L, "맨투맨", 1L,new ArrayList<>()));
        TopChildren.add(createAndSaveChildCategoryV2(4L, "반팔 셔츠", 1L,new ArrayList<>()));
        TopChildren.add(createAndSaveChildCategoryV2(5L, "긴팔 셔츠", 1L,new ArrayList<>()));
        TopChildren.add(createAndSaveChildCategoryV2(6L, "반팔티", 1L,new ArrayList<>()));
        TopChildren.add(createAndSaveChildCategoryV2(7L, "긴팔티", 1L,new ArrayList<>()));
        TopChildren.add(createAndSaveChildCategoryV2(8L, "니트/스웨터", 1L,new ArrayList<>()));
        TopChildren.add(createAndSaveChildCategoryV2(9L, "블라우스", 1L,new ArrayList<>()));
        createAndSaveParentCategory(1L, "상의", TopChildren);

        // "하의"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
        List<Category> bottomChildren = new ArrayList<>();
        bottomChildren.add(createAndSaveChildCategoryV2(11L, "긴바지", 10L, new ArrayList<>()));
        bottomChildren.add(createAndSaveChildCategoryV2(12L, "반바지", 10L, new ArrayList<>()));
        bottomChildren.add(createAndSaveChildCategoryV2(13L, "치마", 10L, new ArrayList<>()));
        createAndSaveParentCategory(10L, "하의", bottomChildren);

        // "dress&set"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
        List<Category> setChildren = new ArrayList<>();
        setChildren.add(createAndSaveChildCategoryV2(15L, "원피스", 14L, new ArrayList<>()));
        setChildren.add(createAndSaveChildCategoryV2(16L, "투피스", 14L, new ArrayList<>()));
        setChildren.add(createAndSaveChildCategoryV2(17L, "셋업", 14L, new ArrayList<>()));
        createAndSaveParentCategory(14L, "dress&set", setChildren);

        // "아우터"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
        List<Category> outerChildren = new ArrayList<>();
        outerChildren.add(createAndSaveChildCategoryV2(19L, "숏패딩", 18L, new ArrayList<>()));
        outerChildren.add(createAndSaveChildCategoryV2(20L, "롱패딩", 18L, new ArrayList<>()));
        outerChildren.add(createAndSaveChildCategoryV2(21L, "가디건", 18L, new ArrayList<>()));
        outerChildren.add(createAndSaveChildCategoryV2(22L, "재킷", 18L, new ArrayList<>()));
        outerChildren.add(createAndSaveChildCategoryV2(23L, "코트", 18L, new ArrayList<>()));
        outerChildren.add(createAndSaveChildCategoryV2(24L, "무스탕", 18L, new ArrayList<>()));
        outerChildren.add(createAndSaveChildCategoryV2(25L, "조끼", 18L, new ArrayList<>()));
        outerChildren.add(createAndSaveChildCategoryV2(26L, "경량패딩", 18L, new ArrayList<>()));
        createAndSaveParentCategory(18L, "아우터", outerChildren);

        // "신발"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
        List<Category> shoesChildren = new ArrayList<>();
        shoesChildren.add(createAndSaveChildCategoryV2(28L, "스니커즈", 27L, new ArrayList<>()));
        shoesChildren.add(createAndSaveChildCategoryV2(29L, "샌들/슬리퍼", 27L, new ArrayList<>()));
        shoesChildren.add(createAndSaveChildCategoryV2(30L, "부츠", 27L, new ArrayList<>()));
        createAndSaveParentCategory(27L, "신발", shoesChildren);

        // "악세서리"에 대한 하위 카테고리 생성 후 , 하위 카테고리로 다음을 추가
        List<Category> accessoryChildren = new ArrayList<>();
        accessoryChildren.add(createAndSaveChildCategoryV2(32L, "모자", 31L, new ArrayList<>()));
        accessoryChildren.add(createAndSaveChildCategoryV2(33L, "양말", 31L, new ArrayList<>()));
        accessoryChildren.add(createAndSaveChildCategoryV2(34L, "가방", 31L, new ArrayList<>()));
        createAndSaveParentCategory(31L, "악세사리", accessoryChildren);
    }
}

 

package PU.pushop.global.dummydata.util;


import PU.pushop.product.entity.ProductColor;
import PU.pushop.product.repository.ProductColorRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

@Component
@RequiredArgsConstructor
public class ProductColorDataUtil {

    private final ProductColorRepository productColorRepository;

    @Transactional
    public List<ProductColor>  generateAndSaveProductColorData() {
        // Red, Orange, Yellow, Green, Blue, Navy, Purple, Black, White, Gray, Pink, Ivory, Beige, Rainbow
        return Arrays.asList(
                createAndSaveProductColor("Red"),
                createAndSaveProductColor("Orange"),
                createAndSaveProductColor("Yellow"),
                createAndSaveProductColor("Green"),
                createAndSaveProductColor("Blue"),
                createAndSaveProductColor("Navy"),
                createAndSaveProductColor("Purple"),
                createAndSaveProductColor("Black"),
                createAndSaveProductColor("White"),
                createAndSaveProductColor("Gray"),
                createAndSaveProductColor("Pink"),
                createAndSaveProductColor("Ivory"),
                createAndSaveProductColor("Beige"),
                createAndSaveProductColor("Rainbow")
        );
    }

    private ProductColor createAndSaveProductColor(String color) {
        Optional<ProductColor> existingProductColor = productColorRepository.findByColor(color);
        if (existingProductColor.isEmpty()) {
            ProductColor productColor = new ProductColor(color);
            return productColorRepository.save(productColor);
        } else {
            return existingProductColor.get();
        }
    }
}

 

package PU.pushop.global.dummydata.util;


import PU.pushop.category.entity.Category;
import PU.pushop.product.entity.Product;
import PU.pushop.product.entity.ProductColor;
import PU.pushop.product.repository.ProductColorRepository;
import PU.pushop.productManagement.entity.ProductManagement;
import PU.pushop.productManagement.entity.enums.Size;
import PU.pushop.productManagement.repository.ProductManagementRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Component
@RequiredArgsConstructor
public class ProductManagementDataUtil {

    private final ProductManagementRepository productManagementRepository;
    private final ProductColorRepository productColorRepository;
    private final Random random = new Random();

    /**
     * Generates ProductManagement entities for the given products, image paths, and colors.
     *
     * @param products    the list of Product objects
     * @param imagePaths  the list of image paths
     * @param colors      the list of colors
     */
    @Transactional
    public void generateProductManagementData(List<Product> products, List<String> imagePaths, List<ProductColor> colors, List<Category> categories) {
        // Get three random colors
        List<ProductColor> randomColors = getRandomThreeColors(colors);

        for (int i = 0; i < imagePaths.size(); i++) {
            // 상품 n 번 + 썸네일 n 번, 색상 3가지에 대해서 상품인벤토리 생성
            String imagePath = imagePaths.get(i);
            Product product = products.get(i);
            // 랜덤한 3가지 색상에 대해 ProductManagement 생성.
            for (ProductColor color : randomColors) {
                ProductManagement productManagement = createProductManagementV2(product, imagePath, color, categories);
                productManagementRepository.save(Objects.requireNonNull(productManagement));
            }
        }
    }

    private List<ProductColor> getRandomThreeColors(List<ProductColor> colors) {
        Collections.shuffle(colors);
        return colors.stream().limit(3).collect(Collectors.toList());
    }

    private ProductManagement createProductManagementV2(Product product, String imagePath, ProductColor color, List<Category> categories) {
        long additionalStock = 0;
        boolean isRestockAvailable = true;
        boolean isRestocked = false;
        boolean isSoldOut = false;
        long initialStock = random.nextInt(1000);
        long productStock = initialStock;

        String[] splitPath = imagePath.split("_");
        String category = splitPath[0];
        String subCategory = splitPath[1];

        // Subcategory matching using the categories list
        Category matchedCategory = null;
        for (Category cat : categories) {
            if (cat.getName().equals(subCategory)) {
                matchedCategory = cat;
                break;
            }
        }

        // If no matching category found, return null or throw an exception
        if(matchedCategory == null) {
            return null; // or throw exception
        }

        // Random size selection
        Size size = Size.values()[random.nextInt(Size.values().length)];

        // Preset color selection
//        ProductColor productColor = new ProductColor(color);

        return new ProductManagement(initialStock, additionalStock, matchedCategory, product, productStock, size, color, isRestockAvailable, isRestocked, isSoldOut);
    }

    public ProductColor getRandomColor() {
        List<ProductColor> colors = productColorRepository.findAll();
        int randomIndex = new Random().nextInt(colors.size());
        return colors.get(randomIndex);
    }

//    private List<ProductColor> getRandomThreeProductColors() {
//        List<ProductColor> allColors = productColorRepository.findAll();
//        Collections.shuffle(allColors);
//        return allColors
//                .stream()
//                .limit(3)
//                .collect(Collectors.toList());
//    }

    /**
     * Creates a new instance of ProductManagement with random values for fields.
     *
     * @param index the index for creating the ProductManagement instance
     * @return a new instance of ProductManagement
     */
    private ProductManagement createProductManagementV1(int index) {
        long additionalStock = random.nextInt(500);
        boolean isRestockAvailable = random.nextBoolean();
        boolean isRestocked = random.nextBoolean();
        boolean isSoldOut = random.nextBoolean();
        long initialStock = random.nextInt(1000);
        long productStock = random.nextInt(1000);

        // XSMALL("X-Small"), SMALL("Small"), MEDIUM("Medium"), LARGE("Large"), XLARGE("X-Large"), FREE("Free")
        // 랜덤하게 입력.
        Size size = Size.values()[random.nextInt(Size.values().length)];

        long category_id = random.nextInt(34) + 1; // generate random category id between 1 and 34
        long product_id = random.nextInt(500) + 1; // generate random product id between 1 and 500
        // category_id 만을 가지고 있는 Category
        Category categoryById = Category.createCategoryById(category_id);
        // product_id 만을 가지고 있는 Product
        Product productById = Product.createProductById(product_id);
        // product color 를 1번부터 14번까지 색상중 랜덤하게 들고옵니다.
        ProductColor color = getRandomColor();

        return new ProductManagement(initialStock, additionalStock, categoryById, productById, productStock, size, color, isRestockAvailable, isRestocked, isSoldOut);
    }


}

 

레퍼런스 

[Spring/DB] 데이터베이스에 더미 데이터 추가하는 4가지 방법: data.sql, @PostConstruct, @EventListener(ApplicationReadyEvent.class), @ApplicationRunner