【问题标题】:HQL: Fetch Join Collections from Eager TableHQL:从渴望表中获取连接集合
【发布时间】:2011-03-31 19:41:00
【问题描述】:

我有四张桌子:

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,并初始化其SubNode 和SubNode 子级。 SubNode 被急切地获取,但 SubNode 子级被懒惰地获取。

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

我尝试过类似的方法:

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

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

非常感谢任何帮助。

【问题讨论】:

    标签: sql hibernate hql


    【解决方案1】:

    这里是 Hibernate 参考

    我们可能需要别名的唯一原因是如果我们递归地加入获取进一步的集合

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

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

    你可以

    禁用默认子节点 fetch=FetchType.EAGER 并使用 HQL 查询检索您真正想要的内容 - 它(HQL 查询)有效地覆盖关联和集合的映射文件的外部连接和惰性声明(休眠参考文档)。 POJO in Action book 支持这种方法。

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

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

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

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

    ...

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

    【讨论】:

    【解决方案2】:

    为了使查询正常工作,我必须在 Eager 实体上使用 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 和 LEFT OUTER JOIN FETCH 一起工作,但它确实完全按照我的需要工作。

    【讨论】:

    • 好的 (+1) 只是为了好奇:您是否可以在 sessionFactory.openSession() 和 session.close() 之间显示您的代码 sn-p ???还有你带注释的映射???
    • 哇,这很尴尬......你原来的答案是正确的。代码 sn-p,LEFT OUTER JOIN FETCH rn.SubNode AS sn,是我的实体正常工作所需的代码。 (所有这些混乱都是由于我的测试环境有问题)
    猜你喜欢
    • 2012-04-30
    • 2016-01-18
    • 2014-05-15
    • 2011-08-19
    • 2015-03-10
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    相关资源
    最近更新 更多