如何在 Hibernate 中左加入获取多个孩子?

Posted

技术标签:

【中文标题】如何在 Hibernate 中左加入获取多个孩子?【英文标题】:How to left join fetch multiple children in Hibernate? 【发布时间】:2012-03-25 07:39:24 【问题描述】:

我正在使用 hibernate,但在创建获取对象的所有子对象的 hql 查询时遇到了麻烦。

例如:对象用户有一个汽车列表和一个朋友列表。

要让用户使用他的汽车,我会使用以下查询:

from User u left join fetch u.cars where u.id = ?

这很好用,所以我认为通过以下查询很容易让用户使用他的汽车和他的朋友:

from User u left join fetch u.cars left join fetch u.friends where u.id = ?

但这给了我以下错误:

HibernateException: 不能同时获取多个包

现在我的问题是:在休眠中获取多个孩子的正确方法是什么?

【问题讨论】:

重复:***.com/questions/4334970/…。使用休眠:@LazyCollection(LazyCollectionOption.FALSE) Hibernate cannot simultaneously fetch multiple bags的可能重复 【参考方案1】:

最多有一个子集合必须是包(即声明为列表)。将其他集合声明为 Set,它将起作用。

但请注意,执行此类 fetch 连接会产生行的笛卡尔积。如果两个集合都有 100 个元素,则此类查询将从数据库中检索 10,000 行。有时执行获取一个集合的第一个查询和获取另一个集合的第二个查询会更有效(从而将检索到的行数减少到 200)。这也是避免您遇到的问题的一种方法:

select u from User u left join fetch u.cars where u.id = :id;
select u from User u left join fetch u.friends where u.id = :id;

【讨论】:

很高兴知道。从直观上看,第二个查询实际上会在第一个查询加载的相同用户实体上填充朋友集合。但这就是它的工作原理(感谢缓存)! 这两个 HSQL 查询可以写在一个 @NamedQuery 中吗? @MyTitle:没有。命名查询是一个查询,而不是两个。 如何使用 JPA Criteria 执行 2 个查询?我试过了,但我找不到任何例子。我需要实施您的解决方案,因为我无法从 List 更改为 Set,或任何其他替代方案来避免这种情况。 @Pablo 您执行一个查询,然后执行另一个。我相信您应该找到一个示例,显示轻松执行一个条件查询。【参考方案2】:

您刚刚遇到了 Collection/List (bag) 问题。

这里是一个 Hibernate 官方“问题”的链接:https://hibernate.atlassian.net/browse/HHH-1718。如您所见,它已于 2006 年开放,至今仍在开放。

除了 JB Nizet 提出的建议之外,我建议您在模型中使用 Set 而不是 Collection 或 List(如果可以的话),否则,您也可以将 Collection/List 指定为 FetchMode.SUBSELECT 并作为最后一个选项(实施起来很痛苦),您可以在@OneToMany/@ManyToMany 上使用@IndexColumn。

这篇博文将指导您实施解决方案:http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

换句话说,除了变通方法之外,没有任何解决方案可以完全按照您的意愿去做。

希望这会有所帮助!

编辑:错字

【讨论】:

【参考方案3】:

不可能,因为它对应用程序/数据库来说太重了, 您需要创建 2 个单独的条件并分别检索数据。

Cat cat = sess.createCriteria(Cat.class)
              .add(Restrictions.like("name", "F%"))
              .uniqueResult();

List kitten = sess.createCriteria(Kitten.class)
                  .add(Restrictions.eq("cat", cat))
                  .createCriteria("kittens")
                  .add(Restrictions.like("name", "F%"))
                  .list();

List mate = sess.createCriteria(Mate.class)
                .add(Restrictions.eq("cat", cat))
                .createCriteria("mate")
                .add(Restrictions.like("name", "F%"))
                .list();

【讨论】:

以上是关于如何在 Hibernate 中左加入获取多个孩子?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 中使用 Hibernate/JPA 返回多级 json

Hibernate JPA,加入多个表

使用 Eloquent 在 mysql 中左连接后分别获取相同的命名列

在 Eloquent ORM 中左加入 Where

如何在 Hibernate 中使用加入 Java 程序?

Hibernate如何正确删除@OneToMany中的孩子?