Reputation: 8477
@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(...);
}
// ...
}
if bar throw BizException , even in foo explicitly catch the exception, at final it still rollback and throw below exception
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)
And there are some solutions but I found it's not workable for my situation
e.g.
@Transactional(noRollbackFor=BizException.class)
because in foo
also throw BizException
and in this case it should be rollback.
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void bar()
If explicitly specify propagation is REQUIRES_NEW
, when call bar()
it will create a new session, and only rollback this session. But it exist other scenarios if bar failed all process will rollback.
So now my temporary solution is
public void anotherBarWithoutTransaction(){
// ...
if(meetSomeCondition){
throw new BizException(...);
}
// ...
}
@Transactional
public void bar(){ // only add an annotation
anotherBarWithoutTransaction();
}
In my above case I will directly call anotherBarWithoutTransaction
. But it's not very ideal.
Upvotes: 0
Views: 793
Reputation: 8477
Use programmatic transaction management way to explicitly create a new transaction, e.g.
@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>
Upvotes: 1