无法初始化代理 - 无会话

2022-09-01 09:21:01

我有一个如下所示的错误:

无法初始化代理 - 无会话

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

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

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

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

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

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


答案 1

您的问题是休眠会话仅针对一个请求存在。它在请求开始时打开,在结束时关闭。您猜到了答案:休眠会话在两个请求完成之前关闭。

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

当第二个请求的处理开始时,代码正在尝试访问某个实体(通常是集合的元素),该实体通过休眠状态延迟初始化。实体未附加到休眠会话,因此休眠无法在读取休眠代理之前对其进行初始化。您应该打开一个会话,并在 ajax 请求处理开始时将实体重新附加到该会话。

编辑:

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

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

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

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

当您尝试处理第二个请求时,框架将在 HttpSession 对象中找到上一个请求中的实体。然后,它尝试从延迟初始化的子实体访问属性,该子实体现在是休眠代理对象。休眠代理对象是对真实对象的模仿,当有人尝试访问其属性之一时,它将要求其休眠会话用数据库中的信息填充它。这是您的休眠代理正在尝试执行的操作。但是它的会话在上一个请求处理结束时关闭,所以现在它没有休眠会话来水合(填充真实信息)。

请注意,您可能已经在第二个请求开始时打开了休眠会话,但它不知道包含代理对象的实体,因为此实体是由不同的休眠会话读取的。应将实体重新附加到新的休眠会话。

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

希望它有帮助。


答案 2

推荐