如何过滤 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 &gt; 1000; 然后从结果列表中提取客户的?

【讨论】:

为什么这是个坏主意?

以上是关于如何过滤 JPA/JPQL 中的集合?的主要内容,如果未能解决你的问题,请参考以下文章

JPA JPQL IN 子句:如何在 JPA 中使用 IN 子句?

JPA JPQL IN子句:如何在JPA中使用IN子句?

JPA JPQL简介

JPA JPQL 怎么判断某个字段是不是为空

直接在 JPA / JPQL 中将行插入连接表?

JPA JPQL高级操作