java 在 Swing 应用程序中使用 Hibernate 进行会话管理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/268651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:43:05  来源:igfitidea点击:

Session management using Hibernate in a Swing application

javadatabasehibernateswingsession

提问by Dema

How do you do your Hibernate session management in a Java Desktop Swing application? Do you use a single session? Multiple sessions?

您如何在 Java Desktop Swing 应用程序中进行 Hibernate 会话管理?您使用单个会话吗?多个会话?

Here are a few references on the subject:

以下是有关该主题的一些参考资料:

回答by Vladimir Dyuzhev

Single session. Start transaction when you need to do a set of operations (like update data after dialog box OK button), commit the tx at the end. The connection though is constantly open (since it's the same session), and thus all opportunities for caching can be used by both Hib and RDBMS.

单节。当你需要做一组操作时启动事务(如对话框OK按钮后更新数据),最后提交tx。尽管连接始终处于打开状态(因为它是同一个会话),因此 Hib 和 RDBMS 都可以使用所有缓存机会。

It may also be a good idea to implement a transparent session re-open in case the connection went dead -- users tend to leave applications open for extended periods of time, and it should continue to work Monday even if DB server was rebooted on weekend.

实现透明会话重新打开也可能是一个好主意,以防连接中断——用户倾向于让应用程序长时间保持打开状态,即使数据库服务器在周末重新启动,它也应该在周一继续工作.

Update

更新

Jens Schauder provided a reason to use multiple sessions: partial (unwanted) updates to the session. Well, that comes down to the way you use Hibernate.

Jens Schauder 提供了使用多个会话的理由:会话的部分(不需要的)更新。好吧,这归结为您使用 Hibernate 的方式。

Suppose we have two dialogs open (as in Jens' blog example). If user clicks a radiobox, and we immediately update a Hibernate entity associated with this radiobox, then, when user clicks Cancel, we're in trouble -- session is already updated.

假设我们打开了两个对话框(如 Jens 的博客示例)。如果用户单击一个单选框,我们立即更新与该单选框关联的 Hibernate 实体,然后,当用户单击取消时,我们就会遇到麻烦——会话已经更新。

The right way, as I see it, is to update dialog variables (non-Hibernate objects) only. Then, when user clicks OK, we begin a transaction, merge updated objects, commit the transaction. No garbage gets ever saved into session.

在我看来,正确的方法是仅更新对话框变量(非 Hibernate 对象)。然后,当用户点击 OK 时,我们开始一个事务,合并更新的对象,提交事务。没有垃圾被保存到会话中。

MyHibernateUtils.begin();
Settings settings = DaoSettings.load();
// update setttings here
DaoSettings.save(settings);
MyHibernateUtils.commit(); 

If we implement such a clean separation of concerns, we can later switch to multiple sessions with a simple change of MyHibernateUtils.begin() implementation.

如果我们实现了如此清晰的关注点分离,我们可以稍后通过 MyHibernateUtils.begin() 实现的简单更改切换到多个会话。

As for possible memory leak, well... Transaction.commit() calls Session.flush(), which AFAIK, cleans the cache too. Also, one may manually control the caching policy by calling Session.setCacheMode().

至于可能的内存泄漏,好吧...... Transaction.commit() 调用 Session.flush(),AFAIK 也清理缓存。此外,可以通过调用 Session.setCacheMode() 手动控制缓存策略。

回答by Dema

Problem with "''session per thread''" is good Swing applications do the database access outside the EDT, usually in newly created SwingWorker threads. This way, "''session per thread''" quickly becomes "''session per click''".

“每线程会话”的问题是好的 Swing 应用程序在 EDT 之外执行数据库访问,通常在新创建的 SwingWorker 线程中。这样,“''session per thread''”很快就变成了“''session per click''”。

回答by Jens Schauder

Don't use a single session. For everything but the smallest applications, it will grow, collecting outdated data and become slower and slower, since the dirty check needs to check every entity in the session.

不要使用单个会话。对于除最小应用程序之外的所有应用程序,它都会增长,收集过时的数据并变得越来越慢,因为脏检查需要检查会话中的每个实体。

If you don't need/want lazy loading and tracking of changes by Hibernate, you can use short-lived sessions.

如果您不需要/不希望通过 Hibernate 延迟加载和跟踪更改,您可以使用短期会话。

But if you want to benefit from the power of Hibernate use the approach I described in my blog: http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/

但是,如果您想从 Hibernate 的强大功能中受益,请使用我在博客中描述的方法:http: //blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-应用/

or in the German version:

或在德语版本中:

http://blog.schauderhaft.de/2007/12/17/hibernate-sessions-in-fat-client-anwendungen/

http://blog.schauderhaft.de/2007/12/17/hibernate-sessions-in-fat-client-anwendungen/

AFAIK it is really the same approach described in the http://in.relation.to/Bloggers/HibernateAndSwingDemoAppbut with a recommendation how to actually scope your session: On Session per Frame, with the exception of modal Frames which use the session of the parent Frame.

AFAIK 它确实与http://in.relation.to/Bloggers/HibernateAndSwingDemoApp 中描述的方法相同,但建议如何实际确定会话的范围:On Session per Frame,使用会话的模态框架除外父框架。

Just make sure never to combine objects from different sessions. It will cause lots of trouble.

只要确保永远不要组合来自不同会话的对象。它会带来很多麻烦。

In reply to Vladimirs update:

回复 Vladimirs 更新:

  • The cancel actually works extremely nice with my approach: throw away the session.
  • session.flush does not fix the problem of the evergrowing session when you work with a single session for the application. Of course with the approach, you describe you can work with short-lived sessions which should work ok. BUT
  • you lose a lot: lazy loading only works with attached objects, automatic detection of dirty objects. If you work with detached objects (or objects that aren't entities at all) you have to do this yourself.
  • 取消实际上对我的方法非常有效:扔掉会话。
  • session.flush 不能解决当您为应用程序使用单个会话时会话不断增长的问题。当然,使用这种方法,您描述了您可以使用应该可以正常工作的短期会话。但
  • 你失去了很多:延迟加载仅适用于附加对象,自动检测脏对象。如果您使用分离的对象(或根本不是实体的对象),您必须自己执行此操作。

回答by stili

Use one session per thread (doc) and a version or timestamp column to allow optimistic concurrency and thereby avoiding session-to-instance conflicts. Attach instances to session when needed unless you need long running transactions or a restrictive isolation level.

每个线程使用一个会话 ( doc) 和一个版本或时间戳列以允许乐观并发,从而避免会话到实例的冲突。需要时将实例附加到会话,除非您需要长时间运行的事务或限制性隔离级别。