0

我正在使用我需要使用的 Visual Paradigm 开发一个 Java 项目。Visual Paradigm 正在使用 Hibernate。在我添加 Genady RMI 之前,我的项目运行良好。我还需要使用 RMI。

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

当我运行服务器和客户端时,我遇到了与延迟初始化相关的异常,错误为“没有会话或会话已关闭”:

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”被加载,字符串属性“TopicName”为空。

那么,我能做些什么来保持相同的会话呢?

在此先感谢,我很抱歉,但我的英语很差。我很难用英语解释这种情况,所以再次感谢。

4

1 回答 1

1

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

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

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

有三种解决方案:

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

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

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

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

于 2012-08-28T12:34:06.217 回答