我将用一个例子来解释我的问题。在我的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中存在空对象(实例变量没有值),即使该对象在添加到会话时具有较早的值?
答案 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会话。