Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import com.DecodEat.domain.products.entity.RawMaterial.RawMaterialCategory;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Subquery;
import org.springframework.data.jpa.domain.Specification;

import java.util.ArrayList;
Expand Down Expand Up @@ -39,4 +41,29 @@ public static Specification<Product> hasRawMaterialCategories(List<RawMaterialCa
return rawMaterialJoin.get("category").in(categories);
};
}

public static Specification<Product> hasAllRawMaterialCategories(List<RawMaterialCategory> categories) {
return (root, query, criteriaBuilder) -> {

// 1. 서브쿼리를 생성합니다. 이 서브쿼리는 조건에 맞는 Product의 ID(Long)를 반환할 것입니다.
Subquery<Long> subquery = query.subquery(Long.class);
Root<Product> subRoot = subquery.from(Product.class); // 서브쿼리에서 Product 테이블을 기준으로 삼습니다.

// 2. 서브쿼리 내에서 필요한 조인을 수행합니다.
Join<Product, ProductRawMaterial> subProductRawMaterialJoin = subRoot.join("ingredients");
Join<ProductRawMaterial, RawMaterial> subRawMaterialJoin = subProductRawMaterialJoin.join("rawMaterial");

// 3. 서브쿼리의 핵심 로직: '상품별로 카테고리를 묶고(GROUP BY), 그 개수가 일치하는지 확인(HAVING)'
subquery.select(subRoot.get("id")) // 조건에 맞는 Product의 ID를 선택
.where(subRawMaterialJoin.get("category").in(categories)) // 먼저 카테고리가 검색 대상에 포함되는 제품만 필터링
.groupBy(subRoot.get("id")) // Product ID 별로 그룹화
.having(criteriaBuilder.equal(
criteriaBuilder.countDistinct(subRawMaterialJoin.get("category")), // 각 제품의 유니크한 카테고리 개수를 세고
categories.size() // 그 개수가 우리가 찾는 카테고리 리스트의 전체 개수와 같은지 확인
));

// 4. 메인 쿼리: Product의 ID가 위 서브쿼리 결과 목록에 포함(IN)되는 제품만 최종 선택합니다.
return root.get("id").in(subquery);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public PageResponseDto<ProductSearchResponseDto.ProductPrevDto> searchProducts(S
}

if (categories != null && !categories.isEmpty()) {
spec = spec.and(ProductSpecification.hasRawMaterialCategories(categories));
spec = spec.and(ProductSpecification.hasAllRawMaterialCategories(categories));
}

// Specification과 Pageable을 사용하여 데이터 조회
Expand Down
Loading