在Hibernate中急切地获取是什么意思

时间:2013-06-21 10:30:46

标签: java spring hibernate

我正在阅读ProSpring 3的书,其中概述了如何一起使用Spring和Hibernate。但是,我发现了“你可以急切地获取关联”的声明。我的问题是:

在Hibernate 真正中急切地获取关联是什么意思?这对Hibernate中的查询性能有何影响,甚至影响它?

2 个答案:

答案 0 :(得分:4)

Eager提取意味着当从数据库中查找父实体时,会同时查找所有关联实体。

延迟提取(相反)意味着只查找父实体自己的字段。关联实体将填充代理,如果/何时引用它们,将从数据库中查找它们。

因此,查询性能的主要区别在于关联实体的查找何时发生。通过急切提取,这将始终在加载父级的同时发生,而使用延迟提取时,这将是稍后(并且可能永远不会)。


由于按需行为,懒惰加载听起来像是明显的赢家,但需要记住一些注意事项。首先,您的连接范围很难确定。看起来像普通实体对象的实际上有一个嵌入式数据库连接,可以通过“普通”getter方法(或者更糟的是这些方法的客户端)在任何时候调用它。知道何时可以关闭连接或将其返回池中几乎是不可能的。类似地,当“简单”对象在调试期间没有设置其字段时,此行为可能会导致混淆,或者当您只是迭代从所述“简单”对象上的getter方法返回的集合时抛出SQL异常。

此外,如果关联实体与父实体分开加载,则聚合性能可能会更差。还有另一个SQL往返的额外开销,但更重要的是数据库无法重用连接中的现有查找等。在始终使用关联实体的情况下,急切提取可能会更快更容易支持。

恕我直言(并且从经验来讲),延迟加载应该是一个仔细考虑的优化,在那些很有可能不会使用关系的情况下。

答案 1 :(得分:1)

让我用一个简单的例子来说明这一点:假设您正在尝试编写一个查询来获取具有所有他/她User s(一对多关系)的Post对象。当您急切地提取它意味着Post记录将被加载到您的User对象的持久性上下文中。

如果您正在加载懒惰,则意味着Hibernate不会加载除User对象之外的任何数据。在这两种情况下,Hibernate都会使用代理对象,如果您在懒惰时尝试访问User的{​​{1}},则可能会遇到可怕的Post

我的建议是,在大多数情况下,您应该将所有内容设置为懒惰加载,并且可以在JPQL查询中使用LazyInitializationException语法。这也适用于JOIN FETCH API以及类似的方式。