我正在研究我的一个(相当大的)宠物项目,一个Swing应用程序,它本质上需要多线程。几乎所有用户交互都可能通过互联网从某些远程服务器获取数据,因为我既不控制这些服务器也不控制互联网本身,因此长时间的响应时间是不可避免的。当EDT繁忙时,Swing UI显然无法自行重绘,因此所有远程服务器调用都需要由后台线程执行。
我的问题:
后台线程获取的数据使用来自本地(内存中)数据库的数据“丰富”(远程服务器返回ID /对本地数据库中数据的引用)。这些数据最终会传递到EDT,在那里它成为视图模型的一部分。此时某些实体未完全初始化(启用了延迟抓取),因此用户可能会触发延迟抓取。在JTable中滚动。由于hibernate会话已经关闭,这将触发LazyInitializationException。我不知道什么时候用户可以触发延迟抓取,因此按需创建会话/附加分离的对象在这里不起作用。
我通过以下方式解决了这个问题:
虽然这样可行,但应用程序的性能却遭受了很大的损失(有时几乎无法使用)。减速主要是由每个查询现在提取的大量对象引起的。
我目前正在考虑将应用程序的设计更改为“每个线程的会话数”,并将非EDT线程提取的所有实体迁移到EDT线程的会话(类似于this posting on the Hibernate forums)。
附注:由于所有数据库实体都是只读的(参考数据),因此与数据库更新相关的任何问题都不适用。
在这种情况下如何使用Hibernate 和延迟加载的任何其他想法?
答案 0 :(得分:1)
不要在数据API中公开Session本身。你仍然可以懒惰地做,只需确保每次都从 '数据'线程进行水合作用。你可以使用一个块(可运行的或某种类型的命令类可能是最好的Java在这里可以为你做的),它被包含在执行来自'data'线程的加载异步的代码所包含。当您处于UI代码中时(当然在UI线程上)字段中,某种类型的“数据就绪”事件由数据服务发布。然后,您可以从UI中获取事件使用的数据。
答案 1 :(得分:1)
你可以看看Ebean ORM。这是无会话和延迟加载只是工作。这不能回答你的问题,但确实提出了另一种选择。
我知道Ebean已经内置了对异步查询执行的支持,这对您的场景也很有用。
也许值得一看。
答案 2 :(得分:0)
有两个明显的问题,应该单独解决:
基本思想是为每个帧建立一个会话,不包括使用产卵帧会话的模态帧。这不容易,但它的工作原理。意思是,你不会再获得任何LLE了。
我建议将hibernate对象严格保留在它们源自的后端线程上。仅向ETD提供包装器对象。如果要求这些包装器对象提供值,它们会创建一个请求,该请求将传递给后端线程,最终将返回该值。
我设想了三种包装器实现:
异步:请求该值,并在值可用时收到通知。它会立即返回一些虚拟值。在通知时,它将触发一个PropertyChange事件i.O.通知GUI有关“已更改”的值(从未知值更改为实际值)。
同步:请求该值并等待其可用。
定时:两者之间的混合,等待很短的时间(0.01)秒,然后返回。与异步版本相比,这可以避免大量的更改事件。
作为这些包装器的基础,建议使用JGoodies Binding库的ValueModel:http://www.jgoodies.com/downloads/libraries.html
显然,您需要注意任何操作仅对实际加载的值执行,但由于您不打算进行更新,因此这不应该是一个大问题。
让我以警告结束:我已经考虑了很多,但从未真正尝试过,所以请小心行动。