1 案例背景
由于Spring框架优秀的特性,很多java项目都会集成Spring。其中,Spring的轻量级声明式事务管理极大的简化了开发者对于事务的开发工作。
而我在最近的项目开发过程中,遇到了一个奇怪的事务异常:Transaction rolled back because it has been marked as rollback-only。
这篇案例将会对代码逻辑进行排查,同时对rollback-only异常进行分析。
2 案例分析
为了排查和分析rollback-only异常产生的原因,下面我会通过一个demo来模拟上述方法的调用过程。
2.1 测试用例
项目使用Springboot作为启动方式,Spring进行事务管理,Service层作为AOP事务控制的切入点。事务方法的传播属性为REQUIRED,即表示当前方法必须在一个事务中运行。如果已存在一事务正在进行,则该方法将在现有事务中运行,否则就要开始一个新事务。
为了便于理解与分析,这里简化了引发异常的业务代码,只保留关键部分。
调用过程:
![f9c622b7bc5dfb857826952a262f91f8.png](https://i-blog.csdnimg.cn/blog_migrate/a0b465db4119fd034c9aed8acadb7caa.png)
事务配置类TransactionAdviceConfig.java
@Aspect
@Configuration
public class TransactionAdviceConfig {
private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.hikvision.pbg.cp.ipts.web.modules.service..*.*(..)) ";
@Autowired
DataSource dataSource;
@Bean
public TransactionInterceptor txAdvice() {
DefaultTransactionAttribute txAttrRequired = new DefaultTransactionAttribute();
txAttrRequired.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.addTransactionalMethod("save*", txAttrRequired);
source.addTransactionalMethod("delete*", txAttrRequired);
source.addTransactionalMethod("remove*", txAttrRequired);
source.addTransactionalMethod("update*", txAttrRequired);
return new TransactionInterceptor(transactionManager(), source);
}
@Bean