|
8 | 8 | import com.DecodEat.domain.products.entity.RawMaterial.RawMaterialCategory; |
9 | 9 | import jakarta.persistence.criteria.Join; |
10 | 10 | import jakarta.persistence.criteria.Predicate; |
| 11 | +import jakarta.persistence.criteria.Root; |
| 12 | +import jakarta.persistence.criteria.Subquery; |
11 | 13 | import org.springframework.data.jpa.domain.Specification; |
12 | 14 |
|
13 | 15 | import java.util.ArrayList; |
@@ -39,4 +41,29 @@ public static Specification<Product> hasRawMaterialCategories(List<RawMaterialCa |
39 | 41 | return rawMaterialJoin.get("category").in(categories); |
40 | 42 | }; |
41 | 43 | } |
| 44 | + |
| 45 | + public static Specification<Product> hasAllRawMaterialCategories(List<RawMaterialCategory> categories) { |
| 46 | + return (root, query, criteriaBuilder) -> { |
| 47 | + |
| 48 | + // 1. 서브쿼리를 생성합니다. 이 서브쿼리는 조건에 맞는 Product의 ID(Long)를 반환할 것입니다. |
| 49 | + Subquery<Long> subquery = query.subquery(Long.class); |
| 50 | + Root<Product> subRoot = subquery.from(Product.class); // 서브쿼리에서 Product 테이블을 기준으로 삼습니다. |
| 51 | + |
| 52 | + // 2. 서브쿼리 내에서 필요한 조인을 수행합니다. |
| 53 | + Join<Product, ProductRawMaterial> subProductRawMaterialJoin = subRoot.join("ingredients"); |
| 54 | + Join<ProductRawMaterial, RawMaterial> subRawMaterialJoin = subProductRawMaterialJoin.join("rawMaterial"); |
| 55 | + |
| 56 | + // 3. 서브쿼리의 핵심 로직: '상품별로 카테고리를 묶고(GROUP BY), 그 개수가 일치하는지 확인(HAVING)' |
| 57 | + subquery.select(subRoot.get("id")) // 조건에 맞는 Product의 ID를 선택 |
| 58 | + .where(subRawMaterialJoin.get("category").in(categories)) // 먼저 카테고리가 검색 대상에 포함되는 제품만 필터링 |
| 59 | + .groupBy(subRoot.get("id")) // Product ID 별로 그룹화 |
| 60 | + .having(criteriaBuilder.equal( |
| 61 | + criteriaBuilder.countDistinct(subRawMaterialJoin.get("category")), // 각 제품의 유니크한 카테고리 개수를 세고 |
| 62 | + categories.size() // 그 개수가 우리가 찾는 카테고리 리스트의 전체 개수와 같은지 확인 |
| 63 | + )); |
| 64 | + |
| 65 | + // 4. 메인 쿼리: Product의 ID가 위 서브쿼리 결과 목록에 포함(IN)되는 제품만 최종 선택합니다. |
| 66 | + return root.get("id").in(subquery); |
| 67 | + }; |
| 68 | + } |
42 | 69 | } |
0 commit comments