Java 利用Hibernate延迟加载?

Java 利用Hibernate延迟加载?,java,hibernate,spring,lazy-loading,Java,Hibernate,Spring,Lazy Loading,我有一个域对象,它的属性是包含另一个域对象的集合。这是使用hibernate映射实现的(它最终会在另一个表上执行连接)。默认情况下,Hibernate似乎懒散地实例化此集合。这是一件很棒的事情,因为根据我需要显示的内容,我并不总是需要加载集合 我的问题如下:在编写hibernate查询(在DAO中)时,我使用以下方法打开/关闭会话: Session session = getSessionFactory().openSession(); //query goes here using the s

我有一个域对象,它的属性是包含另一个域对象的集合。这是使用hibernate映射实现的(它最终会在另一个表上执行连接)。默认情况下,Hibernate似乎懒散地实例化此集合。这是一件很棒的事情,因为根据我需要显示的内容,我并不总是需要加载集合

我的问题如下:在编写hibernate查询(在DAO中)时,我使用以下方法打开/关闭会话:

Session session = getSessionFactory().openSession();
//query goes here using the session var
session.close();
问题是:当Hibernate最终懒散地加载我的收藏时,
会话早就关闭了!我怎样才能避开这件事?我假设我必须关闭会话,因为我正在做

这是我得到的错误:

SEVERE: failed to lazily initialize a collection of ...

我知道您为每个DAO操作打开和关闭会话。您可以由所有DAO使用同一个会话,在初始化期间打开,在关闭时关闭。请注意,其中提到“每个操作的会话数”是一种反模式:

“不要使用每操作会话反模式:不要在单个线程中为每个简单的数据库调用打开和关闭会话。”

简言之,一次会议应包含一个工作单元。这可能是单个用户请求(可能包括多个查询),也可能是较长的对话(包括多个屏幕和他们自己的(组)查询)。在后一种情况下,有理由考虑不让会话(=事务)在用户思考时间的较长时间内保持打开状态,但在我看来,您的情况与此不同


如果关闭会话,域对象将分离。您可以打开一个新会话,将对象绑定到该会话,然后加载集合,但对我来说,这看起来相当麻烦。

如果这是在Web应用程序中发生的,那么简单的解决方法是使用or。这些延迟会话的关闭,直到整个请求完成,从而允许您在呈现视图时导航惰性关联

一个更通用的解决方案是重写查询,以便它们明确指定应该提前获取哪些关联。这使您可以在默认情况下保持关联的惰性,同时满足您迫切需要获取关联的特殊情况。请参阅Hibernate文档中的说明

“获取”联接允许关联或 待处理的值集合 与其父级一起初始化 使用单个选择项创建对象。这是 特别适用于 收集它有效地覆盖了 外部连接和延迟声明 关联的映射文件的 和收藏


谢谢我考虑过这样做。我只是不确定它会是什么样子(在哪里初始化,在哪里关闭等等)。这也是标准做法吗?我肯定我不是第一个遇到这个问题的人,所以必须有一个最佳实践方法来处理这个问题……我在这里的回答可能会有所帮助。OpenSessionInViewXYZ是与其他MVC框架一起工作还是仅与Spring MVC一起工作?谢谢,我有一个问题:OpenSessionInviewWinterCeptor/Filter可能是我需要的,但您提到它会延迟关闭会话,直到整个请求完成。如果我的一个视图从未强制加载集合,该怎么办?那么,如果用户没有导航到强制初始化的页面(这不是一个问题吗?),会话不可能永远不会关闭吗?实际上,我想我混淆了“request”@marklai Open session在视图中是一种模式()它可以用于任何web框架,它绝对不是特定于Spring的。@es11:是的,我指的是HTTP请求。无论视图执行什么操作,筛选器都将关闭会话。