@Transactional解析
不生效的情况
- 首先@Transactional注解在私有方法上不生效
原因是生成的代理类访问不到私有方法,所以不会生效
- 如果Spring项目没有开启事务,就是在某个配置类上增加@EnableTransactionManagement开启事务管理的注解,那么也会失效。或者在Spring容器中手动创建事务管理器这个Bean
SpringBoot在@SpringBootApplication注解中开启了事务管理,它的实现原理是去读取spring.factories文件,它会自动加载一些启动类,其中就包含了事务管理启动类
- 抛出的异常不是Error与RuntimeException,而是非运行时异常
默认回滚 Error与 RuntimeException运行时异常
- 异常被内部捕获了
- A方法内部调用了B方法,而且B方法也加了事务注解,这种情况也是不会回滚的。
- 数据库引擎不支持事务,目前常见的InnoDB是支持的
原理分析
Spring的事务管理类实际上是AOP的应用,启动类Spring的事务,相当于关闭了事务的自动提交。
在使用了@Transactional注解的类上,实际上为这个类创建的代理。业务代码如果正常,在方法执行完毕后,向数据库提交事务。如果出错,则再根据注解上的配置决定是不是要回滚。
public abstract class TransactionAspectSupport ...{
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
....
try {
// 这里最终会调用到目标方法
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// 目标方法抛出了异常,根据@Transactional注解属性配置决定是否需要回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
...
//目标方法正常执行完成,提交事务
commitTransactionAfterReturning(txInfo);
....
}