HQL加入查询以急切获取大量关系

时间:2015-10-19 21:49:49

标签: java database performance hibernate jpa

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

问题是,我们遇到的情况是,单个父母有十几个直接关系,一些子关系,其中一些在几个实例中有几十个。结果是一个非常大的交叉产品,导致hql几乎永远地旋转它的轮子。在我们放弃并杀死它之前,我们将记录变为11并且看到了超过100000次迭代。

很明显,虽然这种技术对某些情况很有用,但它的生活中的一切都有限制。但是hibernate中最好的替代品是什么呢?我们不想懒惰加载这些,因为我们会陷入更加糟糕的N + 1情况。

我最好让Hibernate预取所有的行和细节,但一次做一个关系,然后将正确的细节对象水合到正确的父对象,但我不知道它是否这样做一个东西。

建议?

更新

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

然而,我们在hibernate日志记录中非常清楚地看到它进行了100K迭代。是否有可能Hibernate会陷入你的人际关系或某事的循环中?

或许这应该被问为一个新问题?

1 个答案:

答案 0 :(得分:0)

我们的团队使用特殊策略与协会合作。收藏是懒惰的,单一关系也是懒惰的,除了简单结构的引用(例如国家参考)。我们使用fluent-hibernate来加载我们在具体情况下所需的内容。这只是因为流畅的休眠支持嵌套投影。您可以参考此unit test来查看如何部分加载复杂的对象网。单元测试的代码片段

 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