我有一个域对象,其属性是包含另一个域对象的集合。这是使用hibernate映射(最终在另一个表上执行连接)来完成的。默认情况下,Hibernate似乎懒得实例化这个集合。事实证明这是件好事,因为根据我需要显示的内容,我并不总是需要加载这个集合。
我的问题如下:在编写我的hibernate查询时(在我的DAO中),我使用以下内容来打开/关闭会话:
Session session = getSessionFactory().openSession();
//query goes here using the session var
session.close();
问题是:当Hibernate最终懒洋洋地加载我的集合时,Session
一直关闭!我怎么能绕过这个?我假设我必须像我一样关闭会议......
这是我得到的错误:
SEVERE: failed to lazily initialize a collection of ...
答案 0 :(得分:5)
如果在网络应用中发生这种情况,则可以轻松解决此问题,即使用OpenSessionInViewInterceptor或OpenSessionInViewFilter。这会延迟会话的关闭,直到整个请求完成,允许您在渲染视图时导航延迟关联。
更通用的解决方案是重写您的查询,以便它们明确指定应该预先获取哪些关联。这使您可以在默认情况下保持关联的延迟,同时满足您希望它们急切获取的特殊情况。请参阅Hibernate文档中的"fetch joins"说明。
“获取”连接允许关联或 价值集合 与父母一起初始化 使用单个选择的对象。这是 在a的情况下特别有用 采集。它有效地覆盖了 外连接和延迟声明 关联的映射文件 和收藏品
答案 1 :(得分:2)
我知道您为每个DAO操作打开和关闭会话。您可以使用所有DAO使用同一个会话,在初始化期间打开并在关闭时关闭。请注意,Hibernate Reference提到“每个操作的会话”作为反模式:
“不要使用session-per-operation反模式:不要在单个线程中为每个简单的数据库调用打开和关闭Session。”
简而言之,会话应包含工作单元。这可以是单个用户请求(可能包括多个查询),也可以是更长的会话(包括具有自己的(一组)查询的多个屏幕)。在后一种情况下,有理由考虑不让会话(=交易)在长时间的用户思考时间内保持开放,但是你的听起来并不像我这样。
如果您关闭会话,您的域对象将分离。您可以打开一个新会话,将对象绑定到它然后加载集合,但对我来说这看起来很麻烦。