如何在 JPQL 查询中过滤子集合?

Posted

技术标签:

【中文标题】如何在 JPQL 查询中过滤子集合?【英文标题】:How to filter child collection in JPQL query? 【发布时间】:2017-04-12 08:03:09 【问题描述】:

我有以下数据库模型:

Category -< ProductCategory >- Product -< Variant

CategoryProduct 具有多对多关系,ProductVariant 具有一对多关系)

现在我需要获取所有具有活动变体产品的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 1CAT 2)、两个产品(PROD 1PROD 2)并且应该返回三个变体(VAR 1VAR 2VAR 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 查询中过滤子集合?的主要内容,如果未能解决你的问题,请参考以下文章

Firestore 对集合及其文档的子集合进行过滤

包括过滤器子集合[重复]

java中,如何查询一个list并得到list里面子集合的一条数据。

如何根据子集合中的值选择对象?

Firestore 查询子集合路径

是否有 JPA / JPQL 查询来搜索春季作为 JSON 传递的实体子集?