hibernate - 使用 JPQL/HQL 查询分层数据

标签 hibernate postgresql jpa hql jpql

我们正在尝试实现一个简单的分层数据模型,如下所示。

public class Team {
    /* ... */

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "team")
    protected List<Member> members;
}

public class Member {
    /* ... */

    @ManyToOne(fetch = FetchType.LAZY)
    protected Team team;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "member")
    protected List<Assignment> assignments;
}

public class Assigment {
    /* ... */

    @ManyToOne(fetch = FetchType.LAZY)
    protected Member member;
}

映射背后的想法非常简单 - 一个团队由成员组成,而这些成员又被分配了一些职责。

问题:创建一个查询,该查询将返回团队->成员->分配的层次结构,并对分配施加条件(例如,截止日期 < 1 周内)。

目前的解决方案:

  1. 查询所有团队实体并迭代事务中的两级集合,过滤掉那些不在时间范围内的分配。 优点:简单。缺点:可能会产生大量开销。
  2. 以下查询:

    SELECT t FROM Team t
      left join fetch t.members m
      left join fetch m.assignments
    

    不幸的是,即使没有任何条件进行分配过滤,查询也会失败,抛出:

    org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
    

我不明白为什么它不允许同时获取两个关系,因为 Hibernate 文档中显示了一个类似的例子:

from Cat as cat
  inner join fetch cat.mate
  left join fetch cat.kittens child
  left join fetch child.kittens

问题:

  1. 是否可以使用单个 SQL 语句获取具有过滤叶级(分配)的整个树状集合?如果不是,建议的解决方案有哪些可以改进的地方?
  2. 为什么双重提取无法正常工作?

附加信息:我们正在使用 Hibernate 4.3.5.FINAL 和 PostgreSQL。

最佳答案

Is it possible to fetch the whole tree-like collection with filtered leaf-level (assignments) with a single SQL statement? If not, what could be improved in the proposed solution?

是的,这是可能的。但是,您需要更改映射以使用 Set 而不是 List

Why the double fetch does not work properly?

当您尝试获取多个集合时,您不能在同一个查询中有两个或多个 List

因此,将分配或成员从 List 更改为 Set

要过滤您的分配 cannot do that in a fetched clause .如果您想获取所有集合并在分配中进行过滤,您的查询可以是:

SELECT t FROM Team t
  join fetch t.members m -- only for fetch
  join fetch m.assignments -- only for fetch
  join t.members member -- new join to do the where
  join member.assigments assigment -- new join to do the where
  where assigment.anyAttribute = someValue -- filter assigment

但是,正如@Vlad 所说,此解决方案的笛卡尔积可能很大,并在 SQL 结果中带来大量不必要的信息。

关于hibernate - 使用 JPQL/HQL 查询分层数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25139879/

相关文章:

java - 如何处理过时的连接?

postgresql - 如何使用 Spark 数据集写入 PostgreSQL hstore

java - 通过 Hibernate 使用分离对象删除行和引用

java - Spring Boot JPA 使用 Hibernate 在 TABLE 中插入大写名称

java - Hibernate 数据映射到子对象

java - jpa 中生成的表中的顺序错误

sql - 尽管有缓存,搜索查询的性能还是被共同好友限制了 98%

postgresql - 将 postgresql 模式传递给 alembic 迁移

java - Hibernate/JPA 不检测位置参数

java - 在 Spring Boot JPA 中的 DATE TIME 删除