简体   繁体   English

使用CriteriaBuilder进行动态查询:一对多

[英]Dynamic query with CriteriaBuilder: one-to-many

I want to build a query using CriteriaBuilder and Predicate, which will return a list of only those products that have "images". 我想使用CriteriaBuilder和Predicate构建查询,该查询将仅返回具有“图像”的那些产品的列表。 But given the fact that there is relation between the Product and Image @OneToMany, I do not know how to implement it. 但是考虑到产品与Image @OneToMany之间存在关联这一事实,我不知道如何实现它。 For example, using the JpaRepository, I know that this query can be constructed this way: List<Product> findAllByImagesIsNotNull() . 例如,使用JpaRepository,我知道可以通过以下方式构造此查询: List<Product> findAllByImagesIsNotNull()

But I need a dynamic query so, as I understand, it's better to use CriteriaBuilder. 但是我需要一个动态查询,所以据我所知,最好使用CriteriaBuilder。

So, I have two entities: 因此,我有两个实体:

    @Entity
    @Table(name = "products")
    public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    long id;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "product_details_id")
    ProductDetails productDetails;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id")
    Category category;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "lens_color_id")
    LensColor lensColor;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "frame_color_id")
    FrameColor frameColor;

    @OneToMany(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            orphanRemoval = true)
    List<Image> images = new ArrayList<>();

    @Column(unique = true)
    String productNumber;
}

and

    @Entity
    @Table(name = "images")    
    public class Image {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    String imageName;

    String imageType;

    boolean isMainImage;
}

I have two metamodels: 我有两个元模型:

@StaticMetamodel(Product.class)
public abstract class Product_ {

    public static volatile SingularAttribute<Product, LensColor> lensColor;
    public static volatile ListAttribute<Product, Image> images;
    public static volatile SingularAttribute<Product, FrameColor> frameColor;
    public static volatile SingularAttribute<Product, Long> id;
    public static volatile SingularAttribute<Product, String> productNumber;
    public static volatile SingularAttribute<Product, ProductDetails> productDetails;
    public static volatile SingularAttribute<Product, Category> category;

}

and

@StaticMetamodel(Image.class)
public abstract class Image_ {

    public static volatile SingularAttribute<Image, String> imageName;
    public static volatile SingularAttribute<Image, Boolean> isMainImage;
    public static volatile SingularAttribute<Image, Long> id;
    public static volatile SingularAttribute<Image, String> imageType;

}

And this is my query code: 这是我的查询代码:

    public List<Product> findByCriteria(Integer minPrice, Integer maxPrice, List<LensColor> lensColor, List<FrameColor> frameColor) {
        return productDAO.findAll(new Specification<Product>() {
            @Override
            public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Join<Product, ProductDetails> productDetailsJoin = root.join(Product_.productDetails, JoinType.INNER);

                List<Predicate> predicates = new ArrayList<>();

// MY PREDICATE CODE FOR FIND ALL PRODUCTS WITH IMAGES IS NOT NULL

                if (!CollectionUtils.isEmpty(lensColor)) {
                    predicates.add(criteriaBuilder.and(root.get("lensColor").in(lensColor)));
                }
                if (!CollectionUtils.isEmpty(frameColor)) {
                    predicates.add(criteriaBuilder.and(root.get("frameColor").in(frameColor)));
                }
                if (minPrice != null && maxPrice != null) {
                    predicates.add(criteriaBuilder.between(productDetailsJoin.get(ProductDetails_.price), minPrice, maxPrice));
                }

                   return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        });
    }

For *-to-many relation, use a PluralJoin depending on collection type, kind of: 对于多对多关系, PluralJoin根据集合类型使用PluralJoin

Join<Product, Image> joinImages = root.joinList("images", JoinType.INNER);
predicates.add(cb.isNotNull(joinImages.get(Image_.id)));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM