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

Jav*_*Guy 7 java swing multithreading hibernate

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

我的问题:

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

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

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

虽然这有效,但应用程序的性能却遭受了很大的损失(有时几乎无法使用).减速主要是由每个查询现在提取的大量对象引起的.

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

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

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

and*_*nka 1

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