spring中12种事务失效场景


一、代理不生效

1、@Transactional注解最好不要标注在接口方法上。最好直接标注在实现类或实现方法上。

    spring2.0之后如果不在配置文件中指定,默认生成代理的方式为CGLIB,如果@Transactional标注在接口上,而接口的实现类的代理方式如果是CGLIB,将无法解析到@Transactional,事务失效。

2、被final、static关键字修饰的类或方法。

    CGLIB是通过生成目标类子类的方式生成代理类的,被final、static修饰后,无法继承父类与父类的方法了。

3、类方法内部调用

    事务的管理是通过代理执行的方式生效的,如果是方法内部调用,将不会走逻辑,也就调用不到。

4、当前类没有被Spring管理


二、框架或底层不支持

1、不支持非public修饰的方法进行事务管理。

2、多线程调用

3、数据库本身不支持事务

    例如MySQL的Myisam存储引擎不支持事务,只有innodb存储引擎才支持,但mysql5之后默认使用innodb

4、未开启事务

    该问题springboot中不存在,springboot默认开启了事务管理。


三、错误使用@Transactional

1、错误的传播机制

spring中12种事务失效场景_第1张图片

 

2、rollbackFor属性设置错误

    默认情况下事务仅回滚运行时异常和Erroe,不回滚编译时异常,所以如果方法中抛出IO异常,默认情况下也会回滚失败。

3、异常被内部catch

  但是在UserSevice中我们捕获了异常,此时UserService上的事务认为正常提交事务。最后在提交时发现事务只读,已经被回滚,则抛出了上述异常。

  因此这里如果需要对特定的异常进行捕获处理,记得再次将异常抛出,让最外层的事务感知到。

4、嵌套事务

    如果出现同时回滚两个service中的方法,则不需要处理。但是如果出现一个方法中只回滚一个service中报错的数据库操作,有两种方式解决。

    1)直接在service 中的整个方法用try catch包住

    2)在在service中使用Propagation.REQUIRES_NEW传播机制


总结:

spring中12种事务失效场景_第2张图片

 

你可能感兴趣的:(java,数据库,mysql)