HQL:从Eager Table获取加入集合

时间:2010-08-18 21:29:59

标签: sql hibernate hql

我有四张桌子:

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

我需要一个查询,该查询将返回表格中RootNodesSubNode个孩子初始化的所有SubNodeSubNode被急切地提取,但SubNode个孩子很懒惰。

我知道如何编写一个查询,LEFT OUTER JOIN FETCH表的直接子节点并相应地初始化它们。但是,我不知道如何抓住从顶级表中急切获取的表的子项。

我尝试过类似的事情:

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

但是,这总是给我一个错误,即所有者不属于SELECT。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:11)

这里是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 in Action book支持这种方法。

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

以下内容摘自Hibernate常见问题解答(链接已被禁用(据我所知),但我已经保存,然后消失)

在MVC应用程序中,我们如何确保在视图尝试访问所有代理和延迟集合时进行初始化?

  

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

...

  

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

答案 1 :(得分:1)

为了让查询正常工作,我必须在急切的实体上执行INNER JOIN FETCH而不是LEFT OUTER JOIN FETCH

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

说实话,我仍然不确定为什么它与INNER JOIN FETCH vs LEFT OUTER JOIN FETCH一起工作,但它肯定正如我所需要的那样工作。