Hibernate在视图中打开会话:每个请求的事务? [英] Hibernate Open Session in View: Transaction per Request?

查看:124
本文介绍了Hibernate在视图中打开会话:每个请求的事务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Tomcat上对Spring使用Hibernate。我一直在阅读并重新阅读关于该主题的指向 JBoss wiki页的经典内容,并且这有帮助。但它给我留下了一些问题。


  1. 为每个请求启动一个事务的想法困扰着我。我想我可以限制过滤器到某些控制器 - 也许把需要交易的所有控制器都置于伪tx路径之下。但如果你不知道是否需要交易,使用交易不是一个坏主意吗?如果我只是在读取某些请求 - 很可能来自缓存的读取 - 没有事务处理,我会更好吗?


  2. 我读过提到他们如何在服务层处理事务的帖子,我想用Spring来做这件事。但是,过滤器代码是什么样的?如果我只需要调用 sessionFactory.getCurrentSession()就可以了。 )在我的过滤器中,它如何被释放回会话工厂以供重用? (即使在使用事务时,我期望看到 session.close()之类的东西)。谁在告诉会话工厂,该会话可以被重用?

    可能是< ?否则,会话会根据需要从池中提取数据库连接,对吗?
  3. 。如果你的答案将成为Spring文档的一个链接,那么你只会让我哭泣,你不想那么做,是吗?如果人们会以这种方式停止回答与Spring相关的问题,我会付出实际的代价。) 解决方案

您的担忧是有效的,在wiki页面上提供的解决方案太简单了。事务不应该在Web层进行管理 - 应该在服务层进行处理。

正确的实现会打开一个会话并将其绑定到过滤器中的一个线程。没有交易开始。会话处于刷新模式从不 - 只读模式。服务呼叫会将会话设置为刷新模式auto&开始/提交交易。一旦服务方法完成,会话刷新模式将恢复为从不。

还有一个选项可以在过滤器中不打开会话。每个服务层呼叫都会打开一个单独的会话&事务 - 在服务调用完成后,会话没有关闭,但注册为延迟关闭。该会话将在Web请求处理完成后关闭。



Spring提供 OpensessionInViewFilter ,其工作方式如上所述。因此,忽略jboss wiki文章并配置OpensessionInViewFilter - 一切都会好起来的。

SessionFactory.getCurrentSession() - 在内部创建会话并将其分配给本地线程。每个请求/线程都有自己的会话。一旦Web请求处理完成,会话将被关闭。在你的代码中,你只需要使用SessionFactory.getCurrentSession()并且不必关闭它。 jboss wiki页面上的代码示例是错误的 - 它应该在finally块中包含SessionFactory.getCurrentSession()。close()。或者他们可能会使用JTA事务并配置hibernate以与JTA事务一起打开/关闭会话。


I'm using Hibernate with Spring on Tomcat. I've been reading and re-reading the oft pointed to JBoss wiki page on the topic, and that has been helpful. But it leaves me with some questions.

  1. The idea of starting a transaction for every request troubles me. I guess I could limit the filter to certain controllers -- maybe put all my controllers that need a transaction under a pseudo "tx" path or something. But isn't it a bad idea to use transactions if you don't know if you're going to need one? And if I'm just doing reads in some request -- reads that very likely may come from a cache -- aren't I better off without a transaction?

  2. I've read posts mentioning how they handled the transactions at the service layer, and I'd like to do this with Spring. But then what does the filter code look like? I still want the session available in my view for some lazy loading.

  3. If all I have to do is call sessionFactory.getCurrentSession() in my filter, how does it get "freed" back to the session factory for re-use? (I expected to see a session.close() or something, even when using transactions.) Who is telling the session factory that that session can be reused?

  4. Perhaps it's the beginTransaction() call that binds a given database connection to a given session for the duration of a request? Otherwise, a session pulls db connections from the pool as needed, right?

Thanks for your patience with all my questions.

(And if your answer is going to be a link to the Spring documentation, you'll just make me cry. You don't want that, do you? I'll pay real money if people would stop answering Spring-related questions that way.)

解决方案

Your concerns are valid, the solution provided on the wiki page is too simplistic. The transaction should not be managed at the web layer - it should be handled at the service layer.

The correct implementation would open a session and bind it to a thread in the filter. No transaction is started. The session is put in flush mode never - read only mode. A service call would set the session to flush mode auto & start / commit the transaction. Once the service method finishes the session flush mode is reverted back to never.

There is also an option to not open the session in the filter. Each service layer call would open a separate session & transaction - after the service call is done the session is not closed, but registered for deferred close. The session will be closed after the web request processing is complete.

Spring provides OpensessionInViewFilter which works as described above. So ignore the jboss wiki article and just configure the OpensessionInViewFilter - everything will be fine.

SessionFactory.getCurrentSession() - internally creates and assigns the session to a thread local. Each request / thread will have its own session. Once the web request processing is complete the session will be closed. From within your code you just need to use SessionFactory.getCurrentSession() and don't have to close it. The code sample on the jboss wiki page is wrong - it should have a SessionFactory.getCurrentSession().close() in the finally block. Or they might be using JTA transaction and configured hibernate to open/close session in conjunction with the JTA transaction.

这篇关于Hibernate在视图中打开会话:每个请求的事务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆