繁体   English   中英

JPA @OneToMany Fetch Overrides CriteriaQuery Join Condition

[英]JPA @OneToMany Fetch Overrides CriteriaQuery Join Condition

我对 Hibernate 和 Criteria API 很陌生,并且在使用它们时遇到了麻烦。

有两个实体:

@Entity
public class Product {
    @Id
    @GeneratedValue
    private Integer id;

    private String productName;

    @OneToMany(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    private List<ProductPrice> prices = new ArrayList<>();
}

@Entity
public class ProductPrice {
    @Id
    @GeneratedValue
    private Integer id;

    private BigDecimal price;

    private String region;

    private LocalDate startDate;
}

产品有多个 ProductPrices。 每个 ProductPrice 都属于一个 Region。 目标是查询特定区域的产品及其所有历史价格:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Product> cq = cb.createQuery(Product.class);
Root<Product> root = cq.from(Product.class);

ListJoin<Product, ProductPrice> productJoin = root.join(Product_.prices, JoinType.INNER);
productJoin.on(cb.equal(productJoin.get(ProductPrice_.region), "REGION1"));
List<Product> products = em.createQuery(cq.distinct(true)).getResultList();

这将生成以下 SQL 查询:


   select
        distinct product0_.id as id1_1_,
        product0_.productName as productN2_1_ 
    from
        Product product0_ 
    inner join
        (
            Product_ProductPrice prices1_ 
        inner join
            ProductPrice productpri2_ 
                on prices1_.prices_id=productpri2_.id
            ) 
                on product0_.id=prices1_.Product_id 
                and (
                    productpri2_.region=?
                )

我尝试了该查询,它似乎有效,但是一旦在其中一个产品上调用getPrices() ,就会延迟获取产品的价格,如下所示:

    select
        prices0_.Product_id as Product_1_2_0_,
        prices0_.prices_id as prices_i2_2_0_,
        productpri1_.id as id1_3_1_,
        productpri1_.price as price2_3_1_,
        productpri1_.region as region3_3_1_ 
    from
        Product_ProductPrice prices0_ 
    inner join
        ProductPrice productpri1_ 
            on prices0_.prices_id=productpri1_.id 
    where
        prices0_.Product_id=?

这是有道理的,因为关联@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) ,但在这种情况下,对于这个特定的查询,我不想要这种行为。 我没有在 Hibernate UserGuide 或 stackoverflow 上找到这样的例子,所以我想我错过了一些非常明显的东西。 但是,我仍然找不到解决我的问题的方法。

谢谢!

正如上面的评论中提到的, on指定了连接所需的列。 在您的情况下,您需要一个where

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Product> cq = cb.createQuery(Product.class);
Root<Product> root = cq.from(Product.class);

ListJoin<Product, ProductPrice> productJoin = root.join(Product_.prices, JoinType.INNER);
cq.where(cb.equal(productJoin.get(ProductPrice_.region), "REGION1"));
List<Product> products = em.createQuery(cq).getResultList();

另外,你应该看看你的@OneToMany映射是否是这样高效设计的。 这弗拉德·米哈尔西亚的优秀文章介绍如何映射@OneToMany有效:要么让它双向或单向与@ManyToOne

对于延迟加载的问题,请查看延迟初始化。 我真的很喜欢用图表来做这件事。

暂无
暂无

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

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