1.상품 검색

컨트롤러

  1. 먼저, 사용자가 어떠한 항목에 대해 검색할 것인지에 대한 정보를 ProductSearchDto를 만들어 받는다 (사용자가 카테고리에 대한 검색을 하는 지, 상품에 대한 검색을 하는 지 등)
  2. 그러면 모든 상품목록에다 해당 사용자가 검색한 기준에 맞는 데이터를 조회하여 제공하면 된다.
@GetMapping("/list")
    public ResponseEntity<?> productList(Pageable pageable, ProductSearchDto dto){

        Page<ProductResDto> productResDtos = productService.findAll(pageable,dto);
        return new ResponseEntity<>(productResDtos,HttpStatus.OK);
    }
    
---------------------------------ProductSerachDto 클래스---------------------------

    @Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ProductSearchDto {
    private String category;
    private String productName;

}

서비스

public Page<ProductResDto> findAll(Pageable pageable, ProductSearchDto searchDto) {
 Specification<Product> specification = new Specification<Product>() {
      **-->Specification인터페이스는 JPA에서 동적 쿼리를 작성하기 위해 제공되는 인터페이스**
     **==>Specification인터페이스를 즉석에서 구현하여 인터페이스의 추상메서드를 구현**        
            @Override
      public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder){
  **-->Predicate클래스는 조건절을 표현하는 객체로 주로 WHERE,HAVING조건을 생성할 때 사용
   Predicate 객체는 CriteriaBuilder로 생성된다. 
.toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder)에서,
Root<T> root는 쿼리에서 엔티티의 속성에 접근하는 객체, 따라 T에는 엔티티가 들어가야함
CriteriaQuery는 전체 쿼리를 구성하는 객체
CriteriaBuilder criteriaBuilder: 조건,그룹,정렬등을 만들기 위한 객체** 
         
         List<Predicate> predicates = new ArrayList<>();
          if(searchDto.getCategory() != null){**-->사용자가 카테고리로 검색한다면**
              predicates.add(criteriaBuilder.equal(root.get("category"), searchDto.getCategory()));
                            **-->카테코리 속성이 사용자가 입력한 카테고리(검색 카테고리)과 같음을 가지는 조건객체 생성** 
                }           **-->equal대신에 like,and,or이 올 수 있음
                            -->여러개의 조건을 표현하기 위해 Predicate를 리스트로 만들고 조건을 넣음**
                
         if(searchDto.getProductName() != null){**-->사용자가 상품이름으로 검색한다면**
            predicates.add(criteriaBuilder.like(root.get("name"),"%"+searchDto.getProductName()+"%"));
          }                 **-->name칼럼이 %사용자가 입력한 이름%을 포함하는 조건을 가지는 객체를 만듬**
          Predicate[] predicateArr = new Predicate[predicates.size()];
           for(int i=0; i< predicates.size(); i++){
              predicateArr[i] = predicates.get(i);
                }
 -->  **리스트를 배열로 변환하는 작업(List<Predicate> predicates -> Predicate[] predicateArr**            
  **-->왜? 리스트를 배열로 바꿀까 여러 조건 객체를 자유롭게 넣기 위해 리스트로 만들어 넣었고.
criteriaBuilder.and()메서드나 criteriaBuilder.or()메서드는 배열을 매개변수로 받기 때문에 변환함**              
            Predicate predicate = criteriaBuilder.and(predicateArr);
    **->여러 조건(Predicate)을 AND연산으로 조합한 최종조건.
       여기서는 category = 사용자 입력값과 name like %사용자입력값% 을 and조건으로 묶은것**         
             return predicate;
            }
        };
  **==> 추상메서드 구현이 끝났고, 이제는 이 어떻게 데이터를 조회할지 조건에 대한 정보가
  specification객체에 담겼고 이것을 매개변수로 데이터를 불러오면 된다.
 -->우리는 위에서 인터페이스를 즉석에서 구현하여 객체를 만든 익명 클래스 방식을 사용했기때문에
 인터페이스지만, specification객체로 사용할 수 있는 것**
     Page<Product> productList = productRepository.findAll(specification,pageable);
               return productList.map(p->p.fromEntity());
   }
    }
  1. Specification 인터페이스의 toPredicate메서드를 익명 클래스 방식으로 구현한다.
  2. 사용자가 입력한 필터 조건에 따라 Predicate객체들을 생성한다.
  3. 여러개의 조건 객체들을 and또는 or로 조합해야하는데 이때 매개변수로 배열로 받기 때문에,
  4. 여러 조건 객체들을 담은 리스트를 배열로 변환한다.
  5. 3번을 통해 최종 조합된 specification객체를 매개변수로 하여 데이터를 조회한다.

레포지토리

@Repository
public interface ProductRepository extends JpaRepository<Product,Long> {
    Page<Product> findAll(Specification<Product> specification, Pageable pageable);
}

2.주문넣기

  1. 현재 주문과 주문상세 테이블이 서로 1:N관계로 조인된 상태다.
  2. 따라서 하나의 주문객체가 생기면 여러 개의 주문 상세 객체가 생기도록해야한다. (예를 들어 청송사과, 대구사과를 한 번에 주문했다면 여기에 대한 주문객체 한개에 청송사과에 대한 상세 주문 한 개와 대구사과에 대한 상세 주문 한개해서 두 개의 상세 주문 객체가 생겨야한다)

컨트롤러

  1. OrderCreateDto는 Ordering이 아니라 OrderDetail에 해당되는 개념이다. (OrderCreateDto는 품목과 주문수량을 받음)