【问题标题】:HQL joined query to eager fetch a large number of relationshipsHQL 加入查询以渴望获取大量关系
【发布时间】:2016-01-18 09:32:11
【问题描述】:

我的项目最近发现 Hibernate 可以采用多个级别的关系,并在单个连接 HQL 中急切地获取它们以生成我们需要的填充对象。我们喜欢这个功能,认为它会胜过惰性获取情况。

问题是,我们遇到了这样一种情况,即单亲父母有大约十几个直接关系,还有几个子关系,其中一些在少数情况下有几十行。结果是一个相当大的交叉产品,导致 hql 几乎永远旋转它的轮子。在我们放弃并杀死它之前,我们将日志记录提高到 11 次,并且看到了超过 100000 次迭代。

很明显,虽然这项技术在某些情况下非常有用,但它也有限制,就像生活中的一切一样。但是,在hibernate中表现最好的替代品是什么?我们不想延迟加载这些,因为我们会陷入 N+1 的情况,情况会更糟。

理想情况下,我希望 Hibernate 预取所有行和细节,但一次只做一个关系,然后将正确的细节对象水合到正确的父级,但我不知道它是否这样做一个东西。

建议?

更新:

所以我们得到了这个查询生成的SQL,结果是我误诊了问题。交叉产品不是那么大。我们直接在我们的数据库中运行相同的查询,并在一秒钟内返回了 500 行。

然而,我们在休眠日志中非常清楚地看到它进行了 10 万次迭代。 Hibernate 是否有可能陷入您的人际关系或其他什么的循环中?

或者也许这应该作为一个新问题提出?

【问题讨论】:

  • 看看JPA Entity Graphs。有了这些,您可以向 JPA 提供者提示您希望急切加载的内容。一个 smart(TM) 提供者将找到一种减少 SELECT 数量的好方法,而不必交叉连接所有实体。 (Hibernate 在这种优化上的表现似乎比 EclipseLink 更好。)

标签: java database performance hibernate jpa


【解决方案1】:

我们的团队使用特殊策略与协会合作。集合是惰性的,单一关系也是惰性的,除了具有简单结构的引用(例如国家引用)。我们使用fluent-hibernate 在具体情况下加载我们需要的内容。这仅仅是因为 fluent-hibernate 支持嵌套投影。您可以参考这个unit test 来了解如何部分加载复杂的对象网络。来自单元测试的代码 sn-p

 List<Root> roots = H.<Root> request(Root.class).proj(Root.ROOT_NAME)
            .innerJoin("stationarFrom.stationar", "stationar")
            .proj("stationar.name", "stationarFrom.stationar.name")
            .eq(Root.ROOT_NAME, rootName).transform(Root.class).list();

另见

How to transform a flat result set using Hibernate

【讨论】:

    猜你喜欢
    • 2014-09-29
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 2019-06-19
    • 2014-02-24
    • 1970-01-01
    • 2014-03-13
    • 2012-09-08
    相关资源
    最近更新 更多