事务失效场景@Transactional
参考文章 :JAVA 事务不生效的常见场景和修改方案
总结:类上要有注解,才能走代理;方法必须是public;
一、
方法所在的类本身,没有交给Spring管理,如缺少@Component、@Service等注解;
Spring事务是由AOP机制实现的,也就是说从Spring IOC容器获取bean时,Spring会为目标类创建代理,来支持事务的。类缺少注解,不是Spring管理的类,无法创建代理。
二、
方法no-public(事务方法不能被private、final、static关键字修饰)
no-public 方法无法被Spring创建代理。
三、
方法内部调用,自己调用自己,没有走代理。
解决方法(核心就是走代理):
1.自己引入自己(引入类本身),@Autowired Impl impl,然后在类中,自己调用自己(impl.get)
2.新建@Service,public方法放在另一个类中;
3.创建新文件,继承ApplicationContextAware,编写getBean方法;
ApplicationContextUtil.getBean(EstimateSaleSingleController.class).test();
4.获取当前类的代理对象 AopContext.currentProxy(); 同过代理对象去获取方法(可以在同一个类中写)。 CommonService commonService = (CommonService) AopContext.currentProxy();
四、
手动选择错误的事务传播属性,即@Transactional注解的propagation属性。
不手动选择,就不会出现问题,默认是REQUIRED:支持当前事务,若是当前没有事务,就新建一个事务。
五、
选择错误的异常处理方式;
1.默认事务回滚是RuntimeException,如果异常是非RuntimeException异常,如IOEException,则事务失效
2.catch 住异常,但不抛出,事务也会失效;(记住必须抛异常才会回滚)
catch (Exception e){
//1.不做任何处理,不抛异常,事务不回滚
e.printStackTrace();
}
catch(Exception e) {
//2.抛出异常,事务生效,会回滚
throw new Exception(“dddd”);
}
六、
配置错误的 @Transactional 注解
1.@Transactional(readOnly = true) readOnly=true 属性指示这是一个只读事务,写数据事务无法生效;
异常信息:SQLException: Connection is read-only. Queries leading to data modification are not allowed 不允许数据修改
2.Transactional(timeout = 60) timeout属性被设置为60秒,超过时间未执行完,则事务失效;
异常信息:Transaction timed out: deadline was Fri Mar 08 18:29:40 CST 2024 (表示事务最后截止时间,从进入这个方法开始计时,到执行操作数据方法时,所在时间大小比)
注意:简单的单表操作语句,没有必要添加事务注解@Transactional。因为事务本身指的是一组操作,要么同时成功、要么同时失败。