单个hibernate会话中的多个事务(使用Spring)

Mik*_*e Q 12 java spring hibernate transactions

是否可以使用Hibernate + Spring对以下内容进行建模.

  • 公开会议
  • 开始交易
  • 做一些工作
  • 承诺
  • 开始交易
  • 更多的工作
  • 承诺
  • 关闭会话

我使用Spring TransactionTemplate来执行会话+事务生命周期范围.

原因是有时我在业务流程中有几个阶段,我想在每个阶段完成后提交.但是我想继续使用相同的持久对象.如果我每个事务都有一个单独的会话,那么我会得到瞬态/分离异常,因为原始会话已关闭.

这可能吗?

Sta*_*sev 6

是的,Hibernate的会话可以开始并提交多个事务.你需要做的是在某个地方存储开放会话,然后重复使用它.注意,Session不是一个线程安全的对象,但是如果你确定它不会出现并发问题,那么你需要的只是TransactionSynchronizationUtils用来将一个会话绑定到线程资源然后在需要时取消绑定它,你可以在这里找到一个例子,或者你可以看看OSIV及其标准实现.

这是一个非常复杂的事情,它更容易,因此您希望立即关闭会话并且不重复使用它,因为它可能会带来麻烦:

  • 缓存中的对象不会被自动驱逐,因此您的会话将大小增加,直到OutOfMemory.
  • 会话内的对象不会被刷新,除非它们是脏的,因此另一个用户更改对象的机会越来越大.确保只有一个用户要更改可写对象.
  • 如果在其中一个步骤中发生某些异常,则必须确保关闭会话.在Session内部发生异常后,此对象不可重用.
  • 如果事务被回滚,Spring会清除会话,因此所有对象都会被分离.如果至少有一个事务被回滚,请确保丢弃所有内容.


Ale*_*nes 2

您可以使用 OpenSessionInView 模式来实现此目的。Spring 提供了一个 javax.servlet.Filter 实现,如果您在 servlet 环境中工作,您可以使用它(问题没有这么说)。这将确保您的 Hibernate 会话在请求期间保持打开状态,而不仅仅是针对单个事务。

此类的 Javadoc非常全面,可能是一个很好的起点。