我正在阅读 ProSpring 3 书,其中概述了如何一起使用 Spring 和 Hibernate。但是,我遇到了“您可以热切地获取关联”的声明。我的问题是:
在 Hibernate 中急切地获取关联的真正含义是什么?这对 Hibernate 中的查询性能有何影响,或者即使它影响了查询的性能?
Eager fetching 是指从数据库中查找父实体时,同时查找所有关联的实体。
Lazy fetching(相反)意味着只查找父实体自己的字段。关联的实体填充有代理,如果/当它们被引用时,这些代理将从数据库中查找它们。
因此,查询性能的主要区别在于关联实体的查找何时发生。使用急切获取这将始终在加载父级的同时发生,而使用延迟获取将更晚(并且可能永远不会)。
由于按需行为,延迟加载听起来像是明显的赢家,但有一些注意事项需要牢记。首先,您的连接范围可能很难确定。看起来像普通实体对象的东西实际上有一个嵌入式数据库连接,可以在任何时候由“普通”getter 方法(或更糟的是这些方法的客户端)调用。几乎不可能知道何时可以关闭连接或将其返回到池中。同样,当“简单”对象在调试期间未设置其字段时,此行为可能会导致混淆,或者当您仅迭代从所述“简单”对象上的 getter 方法返回的集合时会引发 SQL 异常。
此外,如果关联实体与父实体分开加载,则总体性能可能会更差。还有另一个 SQL 往返的额外开销,但更重要的是,数据库不能在连接等中重用现有的查找。在始终使用关联实体的情况下,预取可能会更快,更容易支持。
恕我直言(根据经验),延迟加载应该是经过仔细考虑的优化,在那些很有可能不会使用关系的情况下。
让我用一个简单的例子来说明这一点:假设您正在尝试编写一个查询来获取例如一个User
具有所有他/她Post
的对象(一对多关系)。当您急切地获取时,这意味着Post
记录将与您的User
对象一起加载到持久性上下文中。
如果您延迟加载,则意味着 Hibernate 不会加载除您的User
对象之外的任何数据。在这两种情况下,Hibernate 都将使用Proxy对象,如果您在懒惰时尝试访问您User
的Post
s,您可能会感到害怕LazyInitializationException
。
我的建议是,在大多数情况下,您应该将所有内容设置为延迟加载,并且可以JOIN FETCH
在 JPQL 查询中使用该语法。这Criteria
也以类似的方式与 API 一起工作。