gpt4 book ai didi

java - JPA @OneToMany Fetch 覆盖 CriteriaQuery 连接条件

转载 作者:行者123 更新时间:2023-12-01 18:36:55 25 4
gpt4 key购买 nike

我对 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;
}

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

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 映射是否像这样有效地设计。 This excellent article of Vlad Mihalcea描述如何有效地映射 @OneToMany:使用 @ManyToOne 使其双向或单向。

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

关于java - JPA @OneToMany Fetch 覆盖 CriteriaQuery 连接条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60016640/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com