无法初始化代理 - 没有会话

时间:2013-05-25 18:42:27

标签: java ajax spring hibernate session

我遇到了这样的错误:

  

无法初始化代理 - 无会话

我正在使用java,hibernate和spring。尝试生成PDF文档时出现此错误,我正在按照后续步骤动态生成并存储在数据库中。

  1. 我通过POST方法向应用发送了一个请求。这会动态生成PDF并显示给用户。

  2. 在那个请求之后我发送了另一个请求,但通过ajax请求。这将生成相同的PDF,但会将其保存在数据库中。

  3. 错误显示由于“无法初始化代理 - 无会话”错误而无法执行查询。

    我是否做错了什么,从同一个用户会话中调用两次相同的方法?可能是在两个请求完成之前会话已关闭吗?

    希望有人能帮助我了解正在发生的事情。

1 个答案:

答案 0 :(得分:69)

您的问题是hibernate Session仅适用于一个请求。它在请求开始时打开,在结束时关闭。您猜对了答案:在两个请求完成之前,Hibernate会话已关闭。

到底发生了什么?两个请求期间实体对象都存在。怎么样?它们存储在HTTP会话中(这是一个不同的东西,称为会话)您没有提供有关您正在使用的框架的大量信息,因此我不能给您更多详细信息,但可以肯定您正在使用的框架以某种方式保持您的实体在HTTP会话中。这就是框架如何让您轻松地为多个请求使用相同的对象。

当第二个请求的处理开始时,代码试图访问由hibernate懒惰地初始化的某个实体(通常是集合的元素)。该实体未附加到hibernate会话,因此hibernate在读取之前无法初始化hibernate代理。您应该在ajax请求处理开始时打开一个会话并将实体重新附加到它。

修改

我将尝试简要说明幕后发生的事情。所有java Web框架都有一个或多个servlet来处理请求。 servlet通过创建一个最终产生响应的新线程(HttpResponse)来处理每个请求(HttpRequest)。处理每个请求的方法在该线程内执行。

在请求处理开始时,您的应用程序应分配处理所需的资源(事务,Hibernate会话等)。在处理周期结束时,释放这些资源(提交事务,关闭hibernate会话,释放JDBC连接等)。这些资源的生命周期可以由您的框架管理,也可以由您的代码完成。

为了支持无状态协议中的应用程序状态为HTTP,我们有了HttpSession对象。我们(或框架)在HttpSession上放置了在同一客户端的不同请求周期之间保持相关的信息。

在处理第一个请求期间,hibernate从数据库中读取(懒惰)一个实体。由于延迟初始化,此对象结构的某些部分是hibernate代理对象。这些对象与创建它们的hibernate会话相关联。

当您尝试处理第二个请求时,框架会在HttpSession对象中找到前一个请求中的实体。然后它试图从懒惰初始化的子实体访问属性,现在是一个休眠代理对象。 hibernate代理对象模仿真实对象,当有人试图访问其中一个属性时,它将要求其hibernate会话用数据库中的信息填充它。这就是你的hibernate代理试图做的事情。但是它的会话在前一个请求处理结束时关闭了,所以现在它没有使用hibernate会话来补充水分(填充真实信息)。

请注意,您可能已在第二个请求的开头打开了一个hibernate会话,但它不知道包含代理对象的实体,因为该实体是由另一个hibernate sesion读取的。您应该将实体重新附加到新的hibernate会话。

关于如何重新附加分离的实体有很多讨论,但现在最简单的方法是session.update(entity)

希望它有所帮助。