@Transactional
public void foo(){
doSomthing();
try{
bar();
}catch(BizException e){
logger.warn("call bar failed",e);
// do some work here
}
doSomethingElse();
}
@Transactional
public void bar(){
// ...
if(meetSomeCondition){
throw new BizException(...);
}
// ...
}
如果bar抛出BizException,即使在foo中显式捕获异常,在最终它仍然会回滚并抛出异常
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:720)
并且有一些解决方案,但我发现它对我的情况不可行
e.g。
@Transactional(noRollbackFor=BizException.class)
因为在foo
中也会抛出BizException
,在这种情况下它应该回滚。
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void bar()
如果明确指定传播为REQUIRES_NEW
,则在调用bar()
时,它将创建一个新会话,并且仅回滚此会话。但是,如果bar失败,则所有进程都会回滚。
所以现在我的临时解决方案是
public void anotherBarWithoutTransaction(){
// ...
if(meetSomeCondition){
throw new BizException(...);
}
// ...
}
@Transactional
public void bar(){ // only add an annotation
anotherBarWithoutTransaction();
}
在我的上述情况下,我将直接致电anotherBarWithoutTransaction
。但它并不是很理想。
答案 0 :(得分:0)
使用程序化事务管理方式显式创建新事务,例如
@Autowired
private TransactionTemplate transactionTemplate;
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
barService.bar();
} catch (ApiException e) {
logger.warn("call bar failed",e);
status.setRollbackOnly();
}
}
});
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
<property name="transactionManager" ref="txManager"/>
</bean>