IT 프로젝트/쇼핑몰 만들기

[Spring Boot] 스프링 부트 프로젝트/쇼핑몰 만들기 - 상품 목록 조회

happygram 2020. 1. 25. 20:38

설명

메뉴 선택 시 해당 메뉴에 해당하는 상품의 목록들을 조회하는 기능을 구현 해보겠습니다.

데이터베이스

스키마

이전 글을 참조해서 생성을 진행합니다.
포스팅 하면서 지속적으로 업데이트 하고 있습니다.

데이터베이스 모델 설계

데이터

상품 데이터를 추가합니다.
더 많은 데이터를 추가하시고 싶으신 경우 데이터 모델에 맞게 추가하시면 됩니다.

---- product ----
-- 티셔츠
INSERT INTO product
(name, price, description, image_url, color, size, category_id, discount, create_timestamp, update_timestamp)
VALUES('Color T-shirts', 29800, '남녀 공용으로 누구나 입을 수 있는 티셔츠 입니다. 사이즈가 넉넉히 나왔으니 선택하실 때 참조 하세요.', '/images/clothing-2.png', 'Green,Blue,Purple,Red,Orange', '90,95,100,105', 102, 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

-- 청바지
INSERT INTO product
(name, price, description, image_url, color, size, category_id, discount, create_timestamp, update_timestamp)
VALUES('Blue Jeans', 39800, '일자 청바지입니다.', '/images/pants-2.png', 'Blue,Black', '28,29,30,31,32,33,34', 103, 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

Back-End

Product.java

package happygram.ecommerce.jpa.domain;

import java.time.LocalDateTime;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString
@Getter
@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private Long price;

    private String description;

    private String imageUrl;

    private String color;

    private String size;

    private Long discount;

    private Long categoryId;

    @CreationTimestamp
    private LocalDateTime createTimestamp;

    @UpdateTimestamp
    private LocalDateTime updateTimestamp;

    @Builder
    public Product(String name, Long price, String description, String imageUrl, String color, String size, Long discount, Long categoryId) {
        this.name = name;
        this.price = price;
        this.description = description;
        this.imageUrl = imageUrl;
        this.color = color;
        this.size = size;
        this.discount = discount;
        this.categoryId = categoryId;
    }
}

ProductRepository.java

package happygram.ecommerce.jpa.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import happygram.ecommerce.jpa.domain.Product;

@Repository
public interface ProductRepository extends JpaRepository<Product, Long>{

    /**
     * 메뉴 아이디로 상품 목록 조회
     * @param categoryId
     * @return
     */
    List<Product> findAllByCategoryId(Long categoryId);

}

ProductService.java

package happygram.ecommerce.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import happygram.ecommerce.jpa.domain.Product;
import happygram.ecommerce.jpa.repository.ProductRepository;

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    /**
     * 메뉴 아이디로 상품 목록 조회
     * @param categoryId
     * @return
     */
    public List<Product> getProductList(Long categoryId){
        return productRepository.findAllByCategoryId(categoryId);
    }

}

ProductController.java

package happygram.ecommerce.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import happygram.ecommerce.jpa.domain.Product;
import happygram.ecommerce.service.ProductService;

@Controller
@RequestMapping("/product")
public class ProductController {

   @Autowired
   private ProductService productService;

   /**
    * 상품 상세 조회
    */
   @RequestMapping(value = "/view/detail")
   public String viewProductDetail(Model model) {
      model.addAttribute("template", "fragments/content/product/detail");
      return "index";
   }

   /**
    * 상품 목록 조회
    * @param id
    * @param model
    * @return
    */
   @RequestMapping(value = "/view/list/{id}")
   public String viewProductList(@PathVariable Long id, Model model) {

      // data
      List<Product> productList = productService.getProductList(id);
      model.addAttribute("productList", productList);

      // view
      model.addAttribute("template", "fragments/content/product/list");
      return "index";
   }

}

Front-End

list.html

<div class="content-wrapper">
    <!-- Main content -->
    <section class="content">
        <section class="content-header">
            <div class="container-fluid">
              <div class="row mb-2">
                <div class="col-sm-6">
                  <h1>E-commerce</h1>
                </div>
                <div class="col-sm-6">
                  <ol class="breadcrumb float-sm-right">
                    <li class="breadcrumb-item"><a href="#">Home</a></li>
                    <li class="breadcrumb-item active">E-commerce</li>
                  </ol>
                </div>
              </div>
           </div><!-- /.container-fluid -->
        </section>
        <div class="row">
            <div class="col-md-4" th:each="product : ${productList}">
                <div class="card card-outline">
                    <div class="card-body">
                        <!-- image -->
                        <div class="text-center">
                            <a th:href="@{/product/view/detail}">
                                <img class="img-fluid" th:src="@{'/static/' + ${product.imageUrl}}" alt="Product picture">
                            </a>
                        </div>
                        <!-- main -->
                        <a th:href="@{/product/view/detail}">
                            <h3 class="text-dark profile-username text-center" th:text="${product.name}"></h3>
                            <p class="text-muted text-center" th:text="${product.size}"></p>
                            <p class="text-dark text-center" th:text="${product.price}"></p>
                        </a>
                        <!-- sub -->
                        <ul class="list-group list-group-unbordered mb-3">
                            <li class="list-group-item">
                                <i class="fas fa-reply"></i> <b>Review</b> <a class="float-right">1,322</a>
                            </li>
                            <li class="list-group-item">
                                <i class="fas fa-star"></i> <b>Star</b> <a class="float-right">2,549</a>
                            </li>
                        </ul>
                        <!-- badge -->
                        <span class="right badge badge-danger">주문 폭주</span>
                        <span class="right badge badge-warning">한정 수량</span>
                    </div>
                </div>
            </div>
        </div>

    </section>
</div>