如何在 JPQL 查询中过滤子集合?
Posted
技术标签:
【中文标题】如何在 JPQL 查询中过滤子集合?【英文标题】:How to filter child collection in JPQL query? 【发布时间】:2017-04-12 08:03:09 【问题描述】:我有以下数据库模型:
Category -< ProductCategory >- Product -< Variant
(Category
与Product
具有多对多关系,Product
与Variant
具有一对多关系)
现在我需要获取所有具有活动变体产品的Category
记录。我通过以下 JPQL 查询获取这些对象:
@Query("select distinct c from Category c join c.products as p join p.variants as pv where pv.active = true")
效果很好 - 准确返回类别 - 但是每个 Category
都包含 所有 产品 - 不仅 这些具有 active 变体。
如何过滤掉在单个查询中处于非活动状态的产品(或变体)?
Here 是一个带有数据库结构和示例数据的 postgres 脚本。对于给定的数据,两个类别(CAT 1、CAT 2)、两个产品(PROD 1、PROD 2)并且应该返回三个变体(VAR 1、VAR 2、VAR 3)。
【问题讨论】:
【参考方案1】:我遇到了完全相同的问题,我花了一段时间才弄清楚它是如何工作的。当您在 JOIN
之后添加 FETCH
时,应过滤子列表,如下所示:
SELECT DISTINCT c FROM Category c JOIN FETCH c.products as p join p.variants as pv where pv.active = true
【讨论】:
在我看来,这种方法比实际工具更像是一种 hack,因为它不稳定。如果在执行这个查询之前我们(在同一个事务中)以正常方式获取一些产品(比如 P1 和 P2),它们会连同它们所有对应的变体一起被获取,对吧?假设我们然后执行查询,并且某个类别 C1 包含 P1 和 P2。 JPA 不会再次重新获取那些产品 P1 和 P2 - 因为这自然会覆盖 EntityManager 中已经获取的 P1 和 P2;它重用了 EM 中的 P1 和 P2。因此,C1.products 将包含 P1 和 P2 及其所有变体,而不仅仅是活动的。 因此,根据我们在执行查询之前获取的实体,它可能会按预期过滤或不过滤项目。我说这还不够好。 我认为这个答案适用于@MaksimGumerov 提到的警告【参考方案2】:我也遇到了同样的问题,发现@OneToMany注解中的FetchType很重要。它需要设置为懒惰模式。如果是 Eager 模式,jpa 将创建 sql 查询以从表中为您的子集合获取数据,并且不会为您过滤它。
【讨论】:
以上是关于如何在 JPQL 查询中过滤子集合?的主要内容,如果未能解决你的问题,请参考以下文章