如何过滤 JPA/JPQL 中的集合?
Posted
技术标签:
【中文标题】如何过滤 JPA/JPQL 中的集合?【英文标题】:How to filter collection in JPA/JPQL? 【发布时间】:2010-10-15 03:05:01 【问题描述】:我有两个实体:
@Entity
public class Customer implements java.io.Serializable
...
@OneToMany(fetch=FetchType.EAGER, mappedBy="customer")
private Set<CustomerOrder> customerOrders;
...
@Entity
public class CustomerOrder implements java.io.Serializable
....
private double cost;
@ManyToOne
@JoinColumn(name="CUST_ID")
public Customer customer;
...
现在在我的 JPQL 中,我想以 CustomerOrder.cost>1000 退回这些客户。例如,有三个客户 A、B 和 C。A 有两个订单,成本分别为 1000 和 2000。 B 有三个订单,成本分别为 2000,3000 和 500。 C 有一个订单,成本=500。现在我想得到三个客户: A 只返回成本=2000 的订单; B返回2000和3000的订单; C 返回一个空的订单集合。
但以下将始终返回完整集合:
select c from Customer c, in(c.customerOrders) o where o.cost>1000
我如何在 JPQL 或 Hibernate 中做到这一点?
【问题讨论】:
【参考方案1】:发布的查询相当于
select c from Customer c inner join c.customerOrders o where o.cost > 1000
它只返回至少有一个订单成本大于 1000 的所有客户。
我建议反向连接和选择订单 - 虽然它在语义上相同但在结构上与您想要的结果不同:
select o from CustomerOrder o where o.cost > 1000
现在,Hibernate 具有称为 Filter 的非 JPA 功能,它应该完全满足您的需求 - 请参见此处: http://www.hibernate.org/hib_docs/reference/en/html/filters.html
【讨论】:
jscoot 说它返回所有行,所以你的第一个查询可能不等于他的查询,因为 C 只有一个订单,它的成本是 【参考方案2】:试试这个
select c from Customer c join CustomerOrder o with o.cost > 1000
如果客户有两个成本> 1000的订单,它可能会返回两次, 您可以对其进行分组
select c from Customer c join CustomerOrder o with o.cost > 1000
group by c
【讨论】:
【参考方案3】:在那里有 OneToMany 关系听起来是个坏主意(在性能方面)。
但是为什么这不起作用:select o from CustomerOrder o where o.cost > 1000;
然后从结果列表中提取客户的?
【讨论】:
为什么这是个坏主意?以上是关于如何过滤 JPA/JPQL 中的集合?的主要内容,如果未能解决你的问题,请参考以下文章