@Transactional不生效的场景
@Transactional概述
@Transactional注解可以加在方法、类和接口上,加在类和接口上等于给类中的每个public方法都添加了@Transactional,在使用时尽量直接加在方法上。@Transactional属性及说明见下表:
- name:一般只有1个事务管理器,默认即可,无需指定。
- propagation:事务的传播行为。默认是Propagation.REQUIRE适用百分之90的场景,默认即可
- isolation:事务隔离级别,默认即可
- timeout:事务超时时间,默认即可
- readOnly: 是否只读事务,默认即可
- rollbackFor:触发事务回滚的异常类型。这个就不能随便默认了,@Transactional只能检测到unchecked异常和error。
- noRollbackFor: 触发事务回滚的异常类型。默认即可
PS:
- 比如RuntimeExeption,NointerException...等编译器在编译前检测不出来的异常,属于unchecked异常。
- 像checked异常,如IOException...等编译器可检测出来,即需开发人员手动处理(try-catch或者throws)的异常是检测
@Transactional常见不生效的场景
用在非public方法
@Transactional修饰的方法必须是public,不然会失效。
同一个类中,非@Transactional方法调用@Transactional方法
举个简单的例子,AController调AService的A方法,A方法再调用 AService的B方法,B方法上加了@Transactional;这种场景是会失效的,即使多次更新操作数据库都在B方法里也同样
如何避免:建议大家在调用链首个被调用Service方法上加@Transactional。按上面的举例,即在A方法上加
Service方法中使用try-catch
很简单,在方法中抛出异常被try-catch捕获了,@Transactional会认为是正常执行,不会进行回滚
如何避免:尽量少在service中使用try-catch,可以放到controller进行处理。如果非要使用,也请记得catch中再抛出unchecked异常
方法抛出checked异常
@Transactional只能监测到unchecked异常;如果是checked异常,可以使用rollbackFor指定具体的checked异常,这样就可以拦下来进行回滚了