问题描述:
问题代码示意:
ClassA{
@Transactional
methodA(){
try{
ClassB.methodB();}
catch{}
}
}
ClassB{
@Transactional
methodB(){
do something;
}
}
报错提示:
org -springframenork transaction.UnexpectedRolbackException:Transaction rolled back because it has been marked as rollback-only at ong.springframeaork.transaction.support.bstractplatformiTransactionManager . processRollback(AbstractPlatfornTransactionNanager . java:873)at org.springframework.transaction.support.AbstractplatfornTransactionwanager.conmit(AbstractplatformTransactionManager. java:710) at org.springframeaork.transaction.interceptor .TransactionAspectsupport.comitTransactionAfterReturning(Transactionspectsupport.java:535)at ong.springframework.transaction.interceptor . Transactionkspectsupport.invokewithinTransaction(TransactionAspectsupport.java:305) at org.springframework.transaction.interceptor . TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectivewethodInvocation.proceed(ReflectiveMethodInvocation.java:186)at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy . java:691)
原因分析:
事务传播行为的问题:因为都是同一个事物 然后B要回滚 在内部已经标记这个事物要回滚了 但是在A的逻辑中在提交的时候发现 这个事物是要回滚的 所以就冲突了
事务调用链路(事务传播性:org.springframework.transaction.TransactionDefinition#PROPAGATION_REQUIRED):A->B->C 时,在C中调用出现异常之后,该异常被Spring事务管理器捕获之后标记事务回滚;C执行返回A时,A对B->C的调用异常进行了try-catch之后吞没了异常而没有再次抛出,因此A方法结束之后Spring事务管理器认为事务是可以提交的,但是在C方法已经标记失败,因此冲突抛出异常。
解决方案:
B方法的传播行为改为REQUIRES_NEW ,手动提交事务。
ClassA{
@Transactional
methodA(){
try{
ClassB.methodB();}
catch{}
}
}
ClassB{
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
methodB(){
do something;
// 此处我们吞没了异常以为了事务是可以提交的,但是由于insert主键冲突Hibernate事务事务管理器标记为回滚,因此在Spring真正进行事务提交检查时候会失败
// 抛出异常:org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
// 手动标记事务回滚,此处标记回滚;该方法执行完毕不会执行提交操作,直接回滚因此不会有如上异常
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}



