【问题标题】:How to filter child collection in JPQL query?如何在 JPQL 查询中过滤子集合?
【发布时间】: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)。

【问题讨论】:

    标签: java spring jpa spring-data jpql


    【解决方案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 查询以从表中为您的子集合获取数据,并且不会为您过滤它。

    【讨论】:

      猜你喜欢
      • 2021-03-16
      • 2010-10-15
      • 2014-05-04
      • 1970-01-01
      • 2016-03-08
      • 2023-03-26
      • 1970-01-01
      • 2020-06-11
      • 2019-12-04
      相关资源
      最近更新 更多