1

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

在 Hibernate 中急切地获取关联的真正含义是什么?这对 Hibernate 中的查询性能有何影响,或者即使它影响了查询的性能?

4

2 回答 2

4

Eager fetching 是指从数据库中查找父实体时,同时查找所有关联的实体。

Lazy fetching(相反)意味着只查找父实体自己的字段。关联的实体填充有代理,如果/当它们被引用时,这些代理将从数据库中查找它们。

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


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

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

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

于 2013-06-21T10:38:13.070 回答
1

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

如果您延迟加载,则意味着 Hibernate 不会加载除您的User对象之外的任何数据。在这两种情况下,Hibernate 都将使用Proxy对象,如果您在懒惰时尝试访问您UserPosts,您可能会感到害怕LazyInitializationException

我的建议是,在大多数情况下,您应该将所有内容设置为延迟加载,并且可以JOIN FETCH在 JPQL 查询中使用该语法。这Criteria也以类似的方式与 API 一起工作。

于 2013-06-21T10:39:19.200 回答