java 理解 Spring 事务 - 当一个事务方法调用另一个事务方法时会发生什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4171605/
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
Understanding Spring transactions - What happens when a transactional method calls another transactional method?
提问by David Parks
Just to understand the workings of Spring transactions I want to know what happens in the following case where one method marked as @Transactional
calls another method marked as @Transactional
.
只是为了了解 Spring 事务的工作原理,我想知道在以下情况下会发生什么,其中一个标记为的@Transactional
方法调用另一个标记为的方法@Transactional
。
Assume a the configuration uses all default settings.
假设配置使用所有默认设置。
@Service("myService")
@Transactional
public MyService{
public void myServiceMethod(){
myDAO.getSomeDBObjects();
}
}
@Repository("myDAO")
@Transactional
public MyDAOWithUsesBeyondMyService{
public void getSomeDBObjects(){...}
}
Now if I were to enter MyService.myServiceMethod()
it would clearly start a transaction. Then, upon drilling into myDAO.getSomeDBObjects()
what would happen? Would the fact that a transaction already exist cause no new transaction to be born, or am I creating two transactions here?
现在,如果我要进入,MyService.myServiceMethod()
它显然会开始交易。那么,一旦钻进去myDAO.getSomeDBObjects()
会发生什么呢?交易已经存在的事实是否会导致没有新交易产生,还是我在这里创建了两个交易?
The documentation (quoted below) on Propagation seems to cover this, but I'd like to verify my understanding, it was a little much for my virgin brain to comprehend all at once.
关于传播的文档(下面引用)似乎涵盖了这一点,但我想验证一下我的理解,我的处女脑一下子理解了一点。
Propagation: Typically, all code executed within a transaction scope will run in that transaction. However, you have the option of specifying the behavior in the event that a transactional method is executed when a transaction context already exists. For example, code can continue running in the existing transaction (the common case); or the existing transaction can be suspended and a new transaction created. Spring offers all of the transaction propagation options familiar from EJB CMT. To read about the semantics of transaction propagation in Spring, see Section 10.5.7, “Transaction propagation”.
传播:通常,在事务范围内执行的所有代码都将在该事务中运行。但是,您可以选择在事务上下文已存在时执行事务方法时指定行为。例如,代码可以在现有事务中继续运行(常见情况);或者可以暂停现有事务并创建新事务。Spring 提供了 EJB CMT 中熟悉的所有事务传播选项。要了解 Spring 中事务传播的语义,请参阅第 10.5.7 节,“事务传播”。
回答by Sean Patrick Floyd
Two answers:
两个答案:
a) don't do it. Use @Transactional
in the service layer or the dao layer, but not both (the service layer is the usual choice, as you probably want one transaction per service method)
a) 不要这样做。使用@Transactional
在服务层或DAO层,但不能同时(服务层是通常的选择,因为你可能希望每一个服务方法一个交易)
b) if you do it, what happens depends on the propagation
attribute of the @Transactional
annotation and is described in this section: 10.5.7 Transaction propagation. Basically: PROPAGATION_REQUIRED
means the same transaction will be used for both methods, while PROPAGATION_REQUIRES_NEW
starts a new transaction.
b) 如果这样做,会发生什么取决于注解的propagation
属性,@Transactional
并在本节中描述:10.5.7 事务传播。基本上:PROPAGATION_REQUIRED
意味着相同的事务将用于两种方法,同时PROPAGATION_REQUIRES_NEW
启动一个新事务。
About your comments:
关于您的评论:
Of course I kept reading and realized that, as I'm using proxies, this second method won't be managed by the transactional proxy, thus it's like any other method call.
当然,我一直在阅读并意识到,当我使用代理时,第二种方法不会由事务代理管理,因此它就像任何其他方法调用一样。
That's not true in your situation (only if both methods were within the same class).
在您的情况下情况并非如此(仅当两种方法都在同一个类中时)。
If a bean has methods a
and b
, and a
calls b
, then b
is called on the actual method, not the proxy, because it is called from within the proxy (a bean doesn't know that it is proxied to the outside world).
如果 bean 具有方法a
和b
,并且a
调用b
,则b
在实际方法上调用,而不是在代理上调用,因为它是从代理内部调用的(bean 不知道它已代理到外部世界)。
proxy bean
a() --> a()
|
V
b() --> b()
In your situation, however, a service would have an injected dao object, which would be a proxy itself, so you'd have a situation like this:
但是,在您的情况下,服务会注入一个 dao 对象,该对象本身就是代理,因此您会遇到如下情况:
proxy bean
service a() --> a()
|
/---------/
|
V
dao b() --> b()