使用事务注解@Transactional 之前,应该先了解它的相关属性,避免在实际项目中踩中各种各样的坑点。
@Transactional 的所有可选属性如下:
属性 | 类型 | 默认值 | 说明 |
propagation | Propagation枚举 | PROPAGATION_REQUIRED | 可选的事务传播属性 |
isolation | isolation枚举 | ISOLATION_DEFAULT | 可选的事务隔离级别 |
readOnly | boolean | false | 是否只读 |
timeout | int | -1 | 超时(秒) |
rollbackFor | Class[] | 默认情况下checked exceptions不进行回滚, 仅unchecked exceptions(即RuntimeException 的子类)才进行事务回滚。 | 需要回滚的异常类 |
rollbackForClassName | String[] | {} | 需要回滚的异常类名 |
noRollbackFor | Class[] | {} | 不需要回滚的异常类 |
noRollbackForClassName | String[] | {} | 不需要回滚的异常类名 |
1:遇到检测异常时,事务默认不回滚。
Spring的默认的事务规则是遇到运行异常(RuntimeException及其子类)和程序错误(Error)才会进行事务回滚,显然SQLException并不属于这个范围。如果想针对检测异常进行事务回滚,可以在@Transactional 注解里使用 rollbackFor 属性明确指定异常。
2、@Transaction注解失效
1)、加@Transaction的方法必须是public,否则失效。
2)、在同一个类里,两个@Transaction方法直接嵌套调用会失效。
A方法调用B方法,B方法加上@Transaction注解,如果A,B方法在同一个类里,则方法B的@Transaction注解失效。因为@Transaction注解实现原理是AOP,自身调用不会产生代理对象,AOP无法织入,所以会失效。
解决方法:将A,B方法放在两个类中,或是使用AopContext.currentProxy()
Spring AOP事务 不回滚陷阱 。AopContext.currentProxy()_小冷-CSDN博客
3)、绕过springboot的DataSource获取的数据库连接,事务管理器需要手动配置,否则失效。
4)、Spring是通过TransactionSynchronizationManager类中的ThreadLocal变量来获取事务中的数据库连接,所以如果是多线程调用失效。
5)、如果类和方法上同时加上@Transaction注解,方法上的定义优先 。