一尘不染

在*多线程* Swing应用程序中使用Hibernate进行会话管理

hibernate

我目前正在开发我的一个(相当大的)宠物项目,这是一个Swing应用程序,它本质上需要多线程。几乎所有用户交互都可能通过Internet从某些远程服务器获取数据,因为我既不能控制这些服务器,也不能控制Internet本身,因此不可避免的是需要较长的响应时间。EDT忙时,Swing
UI显然无法重绘自身,因此所有远程服务器调用都需要由后台线程执行。

我的问题:

后台线程获取的数据被本地(内存)数据库中的数据“丰富”(远程服务器返回对本地数据库中数据的ID
/引用)。最终,这些数据将传递到EDT,并成为视图模型的一部分。某些实体此时尚未完全初始化(启用了延迟提取),因此用户可能会通过例如滚动JTable来触发延迟提取。由于hibernate会话已关闭,因此将触发LazyInitializationException。我不知道用户何时可能触发延迟获取,因此按需创建会话/附加分离的对象在这里不起作用。

我通过以下方式“解决”了这个问题:

  • 对整个应用程序使用单个(同步的,因为Session实例不是线程安全的)Session
  • 完全禁用延迟获取

在这种情况下,应用程序的性能受到了极大的损害(有时接近无法使用)。速度下降主要是由于每个查询现在获取的对象过多。

我目前正在考虑将应用程序的设计更改为“每线程会话”,并将非EDT线程获取的所有实体迁移到EDT线程的Session(类似于Hibernate论坛上的此帖子)。

旁注:与数据库更新有关的任何问题都不适用,因为所有数据库实体都是只读的(参考数据)。

关于在这种情况下如何将Hibernate 延迟加载一起使用的其他想法?


阅读 210

收藏
2020-06-20

共1个答案

一尘不染

不要在数据API中公开会话本身。您仍然可以懒惰地执行此操作,只需确保每次都
“数据”线程中进行水化处理。您可以使用一个代码块(可运行的或某种命令类可能是Java可以在这里为您提供最好的Java功能),该代码块由执行“数据”线程异步加载的代码所包装。当您使用UI代码时,(当然在UI线程上)字段会由数据服务发布某种“数据就绪”事件。然后,您可以从UI中的事件使用中获取数据。

2020-06-20