一、自定义异常处理被捕获
我们习惯性的将可能存在异常的函数使用try catch 进行捕获,如果该方法使用了声明式事务注解,那么事务将会失效。
@Transactional
public void tranErrTest() {
// 业务代码
try {
// 模拟异常
int a = 1 / 0;
} catch (Exception e) {
System.out.println(e);
//throw new RuntimeException(e);
}
}
代码分析:
1、业务代码部分省略,一般是需要处理事务问题的数据库更新或删除操作
2、@Transactional 注解标明该方法是一个事务体
3、由于代码模拟了异常产生,此时cacth将会被捕获并打印出异常
4、由于异常被捕获后没有再次抛出,此方法中的事务将会失效。
解决办法:
catch 块中再次将异常抛出即可,如代码注释部分开启事务后才会起作用。
二、抛出检查异常
@Transactional
public void tranErrTest2() throws FileNotFoundException {
// 业务代码
new FileInputStream("abcd");
// 业务代码
}
代码分析:
1、new FileInputStream 将会抛出检查异常FileNotFoundException
2、一丹触发检查异常并没有再事务中声明,Spring将放弃事务处理
解决办法:
在@Transactional中增加回滚属性,如:@Transactional(roolbackFor=Exception.class)
三、非public方法导致事务失效
@Transactional
void tranErrTest3() {
// 业务代码
}
代码分析:
1、注意方法上并没有public修饰,此时@Transactional将会失效
解决办法:
解决办法比较解答,加上public修饰即可。但这种情况在开发中比较容易忽略。
四、方法用final修饰
@Transactional
public final void tranErrTest4() {
// 业务代码
}
代码分析:
1、示例代码中方法使用了final关键字修饰,此时@Transactional将会失效
解决办法:
解决就是如果需要使用Spring的事务管理,不要修饰为final,因为Spring事务底层是通过AOP实现的,如果方法是final或static修饰,那么AOP将无法通过动态代理变成事务方法。