java 单个休眠会话中的多个事务(使用 Spring)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13531122/
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
Multiple transactions in a single hibernate session (with Spring)
提问by Mike Q
Is it possible to model the following using Hibernate + Spring.
是否可以使用 Hibernate + Spring 对以下内容进行建模。
- Open session
- Begin transaction
- Do some work
- Commit
- Begin transaction
- More work
- Commit
- Close session
- 打开会话
- 开始交易
- 做一些工作
- 犯罪
- 开始交易
- 更多的工作
- 犯罪
- 关闭会话
I use the Spring TransactionTemplate which does both session + transaction lifetime scoping.
我使用 Spring TransactionTemplate,它同时进行会话 + 事务生命周期范围界定。
The reason is that sometimes I have a few stages in a business process and I would like to commit after each stage completes. However I would like to continue using the same persistent objects. If I have a separate session per transaction then I get transient/detached exceptions because the original session was closed.
原因是有时我在业务流程中有几个阶段,我想在每个阶段完成后提交。但是我想继续使用相同的持久对象。如果每个事务都有一个单独的会话,那么我会收到瞬态/分离的异常,因为原始会话已关闭。
Is this possible?
这可能吗?
回答by Stanislav Bashkyrtsev
Yes, Hibernate's Sessions can begin and commit several transactions. What you need to do is to store open session somewhere, then reuse it. Note, that Session is not a thread-safe object, but if you're sure it won't have problems with concurrency, what you need is just to use TransactionSynchronizationUtils
to bind a session to the thread resources and then unbind it when desired, you can find an example hereor you can take a look at OSIV and its standard implementations.
是的,Hibernate 的会话可以开始并提交多个事务。您需要做的是将打开的会话存储在某处,然后重用它。请注意,Session 不是线程安全对象,但是如果您确定它不会出现并发问题,那么您需要的只是用于TransactionSynchronizationUtils
将会话绑定到线程资源,然后在需要时解除绑定,您可以在此处找到示例,或者您可以查看 OSIV 及其标准实现。
This is a very complicated thing, it's much easier and thus desirable that you close your session right away and don't reuse it, because it may bring troubles:
这是一件非常复杂的事情,它更容易,因此您可以立即关闭会话并且不要重复使用它,因为它可能会带来麻烦:
- The objects inside of cache are not automatically evicted, thus your Session will grow in size until OutOfMemory.
- The objects inside of session are not flushed unless they are dirty, thus the chance that object was changed by another user is larger and larger. Ensure that only a single user is going to change writable objects.
- If some exception happens during one of steps, you have to ensure you close the session. After exception occurred inside of Session, this object is not reusable.
- If transaction was rolled back, the session is cleared by Spring, thus all your objects become detached. Make sure your discard everything if at least one of transactions was rolled back.
- 缓存中的对象不会自动被逐出,因此您的 Session 将一直增长到 OutOfMemory。
- 除非它们是脏的,否则会话内部的对象不会被刷新,因此对象被另一个用户更改的机会越来越大。确保只有一个用户要更改可写对象。
- 如果在其中一个步骤中发生异常,您必须确保关闭会话。Session内部发生异常后,该对象不可重用。
- 如果事务被回滚,会话将被 Spring 清除,因此您的所有对象都将分离。如果至少有一个事务回滚,请确保丢弃所有内容。
回答by Alex Barnes
You could achieve this using the OpenSessionInView pattern. Spring provides a javax.servlet.Filter implementation which you could use if you're working in a servlet environment (question doesn't say so). This will ensure that your Hibernate session is kept open for the duration of the request rather than just for an individual transaction.
您可以使用 OpenSessionInView 模式来实现这一点。Spring 提供了一个 javax.servlet.Filter 实现,如果您在 servlet 环境中工作,您可以使用它(问题没有这么说)。这将确保您的 Hibernate 会话在请求期间保持打开状态,而不仅仅是针对单个事务。
The Javadoc on this classis pretty comprehensive and might be a good starting point.
这个类的 Javadoc非常全面,可能是一个很好的起点。