一尘不染

HQL:从渴望表中获取联接集合

hibernate

我有四个表:

RootNode // Will return multiple root nodes 
SubNode // Will return one sub node per root node
SubNodeChildren1 // Will return multiple for each sub node
SubNodeChildren2 // Will return multiple for each sub node

和类似的实体结构:

RootNode -> SubNode -> SubNodeChildren1
                    -> SubNodeChildren2

我需要一个查询将返回所有RootNodes与它在表SubNodeSubNode孩子初始化。该SubNode是预先抓取,但SubNode孩子们是懒牵强。

我知道如何编写查询,将查询LEFT OUTER JOIN FETCH表的直接子级并相应地对其进行初始化。但是,我不知道如何获取从顶层表急切获取的表的子级。

我已经尝试过类似的东西:

SELECT rn FROM RootNode AS rn LEFT OUTER JOIN FETCH rn.SubNode.SubNodeChildren1

但是,这总是给我一个错误,即所有者不是SELECT的一部分。

任何帮助是极大的赞赏。


阅读 188

收藏
2020-06-20

共1个答案

一尘不染

Hibernate参考

我们可能需要别名的唯一原因是, 如果我们以递归方式加入以获取其他集合

这意味着您的查询应重写为

select distinct 
    rn
from
    RootNode rn
left join fetch 
    rn.subNode sn
left join fetch 
    sn.subNodeChildren

你可以

禁用默认子节点fetch = FetchType.EAGER并通过使用HQL查询检索您真正想要的内容-它(HQL查询)有效地
覆盖了关联和集合的映射文件的外部联接和惰性声明 (Hibernate参考文档)。“行动”书中的POJO支持此方法。

或将SubNodeChildren的集合启用为fetch = FetchType.EAGER

以下是从Hibernate FAQ中提取的(该链接已被禁用(据我所知),但是我在消失之前已保存)

在MVC应用程序中,当视图尝试访问它们时,如何确保所有代理和惰性集合将被初始化?

一种可能的方法是在转发到视图时使会话保持打开状态(并且事务未提交)。在例如通过servlet过滤器呈现视图后,将关闭/提交会话/事务(另一个示例将使用Maverick中的ModelLifetime.discard()回调)。这种方法的一个难题是,如果在呈现视图时发生异常,则确保会话/事务被关闭/回滚。

另一种方法是简单地使用Hibernate.initialize()强制初始化所有需要的对象。这通常比听起来容易得多。

2020-06-20