你的问题是,休眠会议只适用于一个请求。它在请求开始时打开,最后关闭。你猜对了答案:在两个请求都完成之前,Hibernate会话是关闭的。
究竟发生了什么?您的实体对象在两个请求期间都处于活动状态怎么样?它们存储在HTTP会话中(这是一个不同的东西,称为会话)你不会提供关于你正在使用的框架的很多信息,所以我不能给你更多的细节,但可以肯定的是你正在使用的框架以某种方式保持你的实体在HTTP会话中。这就是框架如何让您轻松处理多个请求的相同对象。
当第二个请求的处理开始时,代码正在试图访问由hibernate懒惰地初始化的某个实体(通常是集合的一个元素)。该实体没有附加到hibernate会话中,因此hibernate在读取hibernate之前无法初始化hibernate代理。您应该打开一个会话,并在ajax请求处理开始时将您的实体重新附加到它。
编辑:
我会尽量给正在发生什么幕后的简要说明。所有java web框架都有一个或多个处理请求的servlet。 servlet通过创建一个将最终产生响应的新线程(HttpResponse)来处理每个请求(HttpRequest)。处理每个请求的方法在该线程内执行。
在请求处理开始时,应用程序应该分配处理所需的资源(Transaction,Hibernate session等)。在处理周期结束时,这些资源被释放(事务被提交,休眠会话被关闭,JDBC连接被释放等)。这些资源的生命周期可以由您的框架管理,也可以由您的代码完成。
为了支持在无状态协议HTTP作为应用程序状态,我们有HttpSession对象。我们(或框架)在HttpSession上放置了同一客户端的不同请求周期之间保持相关的信息。
在第一请求休眠的处理读取(懒惰)从数据库中的实体。由于延迟初始化,此对象结构的某些部分是hibernate代理对象。这些对象与创建它们的hibernate会话相关联。
框架从HttpSession对象先前的请求找到实体,当您尝试处理第二个请求。然后它试图从一个被懒惰初始化的子实体访问一个属性,现在是一个hibernate代理对象。 hibernate代理对象模仿真正的对象,当有人试图访问它的一个属性时,它会要求它的hibernate会话填充来自数据库的信息。这是你的hibernate代理正在尝试做的事情。但是它的会话在前一个请求处理结束时关闭了,所以现在它没有使用hibernate会话来充实(充满真实信息)。
请注意,您可能已经在第二个请求的开始处打开了一个hibernate会话,但它不知道包含该代理对象的实体,因为此实体是由不同的休眠状态读取的。您应该重新将实体附加到新的休眠会话。
有一个关于如何重新连接分离实体很多讨论,但最简单的方法,现在是session.update(entity)
。
希望它有帮助。
错误不谈,为什么让两个不同的调用创建PDF?做一次,坚持它,然后从数据库中检索它。 – Makoto
当我写这个问题时,我想你也是这么想的。但我希望有更多经验的人也能证实这一点。只是为了使它更有用......你能解释为什么在这个特定的场景中“无法初始化代理 - 没有会话”错误?提前致谢。 –
休眠问题。向我们展示Ajax调用背后的代码,以便我们可以帮助您。 – Jukka