使用Hibernate + RMI“没有关闭会话或会话”

时间:2012-08-28 12:19:17

标签: java hibernate session rmi visual-paradigm

我正在使用Visual Paradigm开发一个Java项目,我需要使用它。 Visual Paradigm正在使用Hibernate。我的项目运行正常,直到我添加了Genady RMI。我还需要使用RMI。

在服务器端,我有MainDb管理数据库的所有查询,在客户端我有UserWindow和AdminWindow类实现RMI Remote。这两个类通过RMI获得对象MainDb。

当我运行服务器和客户端时,我有一个与Lazy初始化相关的异常,错误是“没有会话或会话已关闭”:

failed to lazily initialize a collection of role: dcl.UsuarioRegistrado.ORM_TieneVideosFavoritos, no session or session was closed.

据我所知,Hibernate使用的是另一个创建dcl.UsuarioRegistrado对象的会话。问题是我不管理会话,因为类PersistentManager只提供getSession()。 PersistentManager类是VisualParadigm提供​​的用于管理Hibernate的类。

我已尝试将所有内容配置为lazy =“false”,但结果更糟,因为某些实体的属性未正确加载。例如,一个对象“Topic”被加载了String属性“TopicName”为null。

那么,我该怎样做才能维持相同的会话?

提前致谢,我很抱歉,但我的英语很差。我很难用英语解释这种情况,所以,再次,谢谢。

1 个答案:

答案 0 :(得分:1)

这是一个常见问题。当你在一个实体中有一个集合时,Hibernate会在实例中注入一个“Hibernate-aware”集合。因此,您可以获得记住当前会话的内容(“当前”=加载实体的会话),而不是列表。

原因是session ==数据库事务。如果Hibernate使用新会话加载相关实体,那么您可以看到新行,更新行或者您可能会收到错误,因为已删除的行在加载父实体时仍然存在。这将是一团糟。

为确保不会发生这种情况,Hibernate将使用原始会话加载所有相关实体。但代码通常的工作方式不同在一个部分中,您加载实体。会议已结束。然后,在一个完全不相关的部分,你试图加载孩子 - >错误。

有三种解决方案:

  1. 禁用延迟加载。这通常不起作用(加载太多,太慢)。但它不应该导致错误;您的代码中可能存在潜伏的错误。

  2. 加载实体时,从每个集合中获取第一个实体。这将正确初始化集合。这里的优点是你可以在代码中决定何时加载相关实例以及何时使用依赖Hibernate进行延迟加载。

    您也可以只加载您需要的关系;所以这经常解决前一点的问题。缺点是您需要知道其他代码将如何使用您的实体提前。这通常很难甚至不可能。

  3. 您可以使用Session.refresh()创建新会话并将现有对象“附加”到此新会话。请注意,这里需要小心;如果你混合刷新和旧对象,你会收到错误。