Home > OS >  Build specification (Criteria API)
Build specification (Criteria API)

Time:10-08

My entities:

public class Product extends BaseEntity {
    @OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
    List<Price> prices;
}

public class Price extends BaseEntity {

    BigDecimal price;

    @ManyToOne(fetch = FetchType.LAZY)
    Product product;
}

My SearchCriteria:

public class ProductSearchCriteria {

    private Optional<BigDecimal> minP;
    private Optional<BigDecimal> maxP;
}

My Specification:

    public static Specification<Product> priceBetween(Optional<BigDecimal> minP, Optional<BigDecimal> maxP) {
    return (root, query, builder) -> {
        //Subquery<Product> sq = query.subquery(Product.class);
        //CriteriaQuery<Price> priceCriteriaQuery = builder.createQuery(Price.class);
        //Root<Price> priceRoot = sq.from(Price.class);

        return minP.map(min -> {
            return maxP.map(max ->
                    //builder
                    ).orElse(null);
        }).orElse(null);
    };
}

In my specification I am trying to retrieve products with price between(price1, price2), but can't build criteria

I tried(but the generated query is false):

max-> builder.between(root.get(Product_.PRICES), min, max)

CodePudding user response:

I have solved this problem myself by using Join:

 Join<Product, Price> productPriceJoin = root.join(Product_.PRICES, JoinType.LEFT);

max -> builder.between(productPriceJoin.get(Price_.PRICE), min, max))

Complete solution looks like this:

public static Specification<Product> priceBetween(Optional<BigDecimal> minP, Optional<BigDecimal> maxP) {
        return (root, query, builder) -> {
            Join<Product, Price> productPriceJoin = root.join(Product_.PRICES, JoinType.LEFT);
            return minP.map(min -> {
                return maxP.map(max ->
                        builder.between(productPriceJoin.get(Price_.PRICE), min, max))
                        .orElse(null);
            }).orElse(null);
        };
    }
  • Related