在Spring bean中启动新事务 [英] Starting new transaction in Spring bean
问题描述
我们有:
@Transactional(propagation = Propagation.REQUIRED)
public class MyClass implementes MyInterface { ...
MyInterface有一个方法: go()
。
MyInterface has a single method: go()
.
当go()执行时,我们启动一个新的事务,当方法完成时提交/回滚 - 这很好。
When go() executes we start a new transaction which commits/rollbacks when the method is complete - this is fine.
现在让我们说在go()中我们在MyClass中调用一个私有方法,该方法有 @Transactional(propagation = Propagation.REQUIRES_NEW
。看来Spring忽略了 REQUIRES_NEW注释并没有启动新事务。我相信这是因为Spring AOP在接口级别(MyInterface)上运行,并且不拦截对MyClass方法的任何调用。这是正确的吗?
Now let's say in go() we call a private method in MyClass that has @Transactional(propagation = Propagation.REQUIRES_NEW
. It seems that Spring "ignores" the REQUIRES_NEW annotation and does not start a new transaction. I believe this is because Spring AOP operates on the interface level (MyInterface) and does not intercept any calls to MyClass methods. Is this correct?
有没有办法在go()事务中启动一个新事务?是否只能调用另一个 Spring管理bean,其事务配置为REQUIRES_NEW?
Is there any way to start a new transaction within the go() transaction? Is the only way to call another Spring managed bean that has transactions configured as REQUIRES_NEW?
更新:在客户执行 go()
时添加他们是通过引用接口而不是类来实现的:
Update: Adding that when clients execute go()
they do so via a reference to the interface, not the class:
@Autowired
MyInterface impl;
impl.go();
推荐答案
从Spring参考2.5:
From the Spring reference 2.5:
使用代理时,
@Transactional
注释应仅应用于具有公共可见性的
方法。如果您使用@Transactional
注释注释protected,private或
包可见方法,则不会产生错误
,但带注释的方法将不显示配置的事务
设置。
When using proxies, the
@Transactional
annotation should only be applied to methods with public visibility. If you do annotate protected, private or package-visible methods with the@Transactional
annotation, no error will be raised, but the annotated method will not exhibit the configured transactional settings.
所以Spring忽略 @Transactional
关于非公开方法的注释。
So Spring ignores @Transactional
annotation on non-public methods.
此外,
在代理中模式(这是默认值),只有通过代理进入
的外部方法调用才会被截获。这意味着'自调用',
即目标对象中调用目标
对象的其他方法的方法,即使被调用的$ b $也不会在运行时导致实际的事务。 b方法标有@Transactional
!
所以即使你做了你的方法 public
,在同一个类的方法中调用它不会启动新的事务。
So even if you make your method public
, calling it from within a method of same class will not start a new transaction.
你可以使用事务设置中的 aspectj
模式,以便在类中编译与事务相关的代码,并且不会在运行时创建代理。
You can use aspectj
mode in transaction settings so that the transaction related code is weaved in the class and no proxy is created at runtime.
参见参考文件更多细节。
另一种可能的方法是在类本身中获取类的spring代理并在其上调用方法而不是这个
:
Another possible way of doing this is fetching the spring proxy of the class in the class itself and call methods on it rather than this
:
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class SomeService {
@Autowired
private ApplicationContext applicationContext;
private SomeService getSpringProxy() {
return applicationContext.getBean(this.getClass());
}
private void doSomeAndThenMore() {
// instead of
// this.doSometingPublicly();
// do the following to run in transaction
getSpringProxy().doSometingPublicly();
}
public void doSometingPublicly() {
//do some transactional stuff here
}
}
这篇关于在Spring bean中启动新事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!