Mar*_*eon 44 java spring transactions
我们有:
@Transactional(propagation = Propagation.REQUIRED)
public class MyClass implementes MyInterface { ...
Run Code Online (Sandbox Code Playgroud)
MyInterface有一个方法:go().
当go()执行时,我们启动一个新的事务,该事务在方法完成时提交/回滚 - 这很好.
现在让我们说在go()中我们调用MyClass中的私有方法@Transactional(propagation = Propagation.REQUIRES_NEW.似乎Spring"忽略"REQUIRES_NEW注释并且不会启动新事务.我相信这是因为Spring AOP在接口级别(MyInterface)上运行,并且不拦截对MyClass方法的任何调用.它是否正确?
有没有办法在go()事务中启动新事务?是否只能调用另一个配置为REQUIRES_NEW的事务的Spring托管bean?
更新:在客户端执行时添加,go()通过对接口的引用而不是类来执行:
@Autowired
MyInterface impl;
impl.go();
Run Code Online (Sandbox Code Playgroud)
Abh*_*kar 77
从Spring参考2.5:
使用代理时,
@Transactional注释应仅应用于具有公共可见性的方法.如果使用注释对带有保护的,私有的或包可见的方法进行@Transactional注释,则不会引发任何错误,但带注释的方法将不会显示已配置的事务设置.
所以Spring忽略@Transactional了非公共方法的注释.
也,
在代理模式(默认设置)下,只会拦截通过代理进入的"外部"方法调用.这意味着'自调用',即目标对象中调用目标对象的其他方法的方法,即使被调用的方法被标记,也不会在运行时导致实际的事务
@Transactional!
因此,即使您创建了方法public,在同一个类的方法中调用它也不会启动新事务.
您可以aspectj在事务设置中使用模式,以便在类中编译与事务相关的代码,并且不会在运行时创建代理.
有关详细信息,请参阅参考文档.
另一种可能的方法是在类本身中获取类的spring代理并在其上调用方法而不是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
}
}
Run Code Online (Sandbox Code Playgroud)
ska*_*man 42
@Transactional只有当它在一个public方法上时才会被注意到,因为Spring AOP的工作方式.
但是,如果您愿意,可以通过编程方式启动新事务TransactionTemplate,例如
TransactionTemplate txTemplate = new TransactionTemplate(txManager);
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus status) {
// do stuff
}
});
Run Code Online (Sandbox Code Playgroud)
简而言之,您必须通过代理调用方法来实现事务行为.可以在问题中询问的同一个bean中调用"REQUIRES_NEW".要做到这一点,你必须做一个"自我"的参考.在春天,它不是直截了当的.你必须用@Resource注释注入它.
@Service("someService")
public class ServieImpl implements Service {
@Resource(name = "someService")
Service selfReference;
@Transactional
public void firstMethod() {
selfReference.secondMethod();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void secondMethod() {
//do in new transaction
}
}
Run Code Online (Sandbox Code Playgroud)
firstMethod中的调用调用代理而不是"this",它应该使"REQUIRES_NEW"事务起作用.
| 归档时间: |
|
| 查看次数: |
50809 次 |
| 最近记录: |