在HttpSession中从Hibernate Session检索的实例的生命周期

时间:2012-04-26 12:11:46

标签: hibernate servlets httpsession

我将用一个例子来解释我的问题。在我的JSP登录页面中,每个正确的登录都会放置一个名为“User”的Object实例,该实例将用户的数据保存到HttpSession(session.setAttribute("user",userObject))。该对象的创建方式是,该用户的用户名和密码是检查并从HibernateSession中检索User对象的实例('User') 在另一个页面中,当我从HttpSession中检索上面设置的userObject时,可以无错误地检索该对象。但是当调用它的方法时,它会给出异常org.hibernate.LazyInitializationException: could not initialize proxy - no Session。为什么我不能从HttpSession那个userObject,即使我已经把它提前了?

为什么HttpSession中存在空对象(实例变量没有值),即使该对象在添加到会话时具有较早的值?

2 个答案:

答案 0 :(得分:2)

如果User实体具有延迟提取的集合属性,则会发生这种情况。然后,当呼叫者实际需要通过例如数据库访问时,该集合实际上仅填充来自DB的数据。 size()iterator()等。这需要在与检索User时完全相同的Hibernate会话中进行。在设计合理的Web应用程序中,Hibernate会话具有一个HTTP请求响应的生命周期。因此,如果访问集合属性发生在不同的Hibernate会话中(读取:不同的HTTP请求),那么您将获得exaclty这个异常。

要解决此问题,您需要急切地获取集合属性,或者在检索Hibernate#initialize()时在集合属性上使用User

另见:

答案 1 :(得分:1)

这是延迟加载的问题。存储在不同数据库实体中的元素(例如子对象列表)不直接与主实例(您的userObject)一起加载,而是在以后真正访问它们时。优点是,只有真正使用的对象必须从数据库加载。

对于使用延迟加载加载这些额外对象,Hibernate需要一个会话。这是最初用于加载主实例的会话。此实例绑定到会话。如果会话在此期间关闭,则会得到您收到的错误消息。例如,如果按此顺序执行

userObject = session.load(...);
session.close();
userObject.getChildObjects(...); // or whatever the method fetching extra objects is called

然后您收到错误消息。

如何避免此错误:例如

  • 不要关闭会话
  • 在子对象的类映射中禁用延迟加载
  • 在关闭会话之前调用userObject.getChildObjects(...);,即使您在那一刻不使用提取的对象。

将主userObject存储在HttpSession中主要不是问题,但可能在对象存在的同时关闭了Hibernate会话。