写点什么

Java 基础知识总结 -- 事务失效的 12 种场景

作者:阿婷
  • 2022 年 8 月 25 日
    北京
  • 本文字数:1271 字

    阅读完需:约 4 分钟

一 常见问题

1 访问权限问题

private 的方法,导致事务失效,spring 要求被代理方法必须是 public 的。

不加权限的时候,方法默认的是??

2 方法用 final 修饰

spring 事务底层使用了 aop,也就是通过 jdk 动态代理或者 cglib,帮我们生成了代理类,在代理类中实现的事务功能。

final 的方法,在它的代理类中,无法重写该方法,无法添加事务功能。

3 方法内部调用

内部调用其实是通过 this 来调用的。如果要解决,就将这个 Service 本身进行注入


4 未被 spring 管理

通常情况下,通过 @Controller、@Service、@Component、@Repository 等注解,可以自动实现 bean 实例化和依赖注入的功能。

如果忘记加这些注解,这个类就不会交给 spring 管理,就事务失效。

5 多线程调用

spring 的事务是通过数据库连接来实现的。当前线程中保存了一个 map<数据源,数据库连接>。

线程间的数据是隔离的,如果用多线程去调用一个方法的话,就会产生多份 ThreadLocal,从而产生多个数据库连接,数据库也就不一样了。

同一个事务,是指同一个数据库连接,只有拥有同一个数据库连接,才能同时提交和回滚。

6 表不支持事务

引擎是 myisam 的就不支持事务。

7 未开启事务

spring 是需要通过 xml 去配置的。springboot 是默认开启事务的。

二 事务不回滚

1 错误的传播特性

@Transcational(propagation=传播特性),该参数指定事务的传播特性。Spring 目前有 7 种。

  1. REQUIRED 如果当前上下文中存在事务,那么加入该事务,如果不存在事务,创建一个事务,这是默认的传播属性值。

  2. SUPPORTS 如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,则使用非事务的方式执行。

  3. MANDATORY 如果当前上下文中存在事务,否则抛出异常。

  4. REQUIRES_NEW 每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。

  5. NOT_SUPPORTED 如果当前上下文中存在事务,则挂起当前事务,然后新的方法在没有事务的环境中执行。

  6. NEVER 如果当前上下文中存在事务,则抛出异常,否则在无事务环境上执行代码。

  7. NESTED 如果当前上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。

目前能创建新事务的三种传播特性:Required、requires_new、nested。

2 自己吞了异常

事务不会回滚,开发者在代码中手动 try…catch 了异常


3 手动抛了别的异常

开发者没有手动捕获异常,但是抛得异常不正确,spring 事务也不会回滚


如上:开发捕获异常,又手动抛出了异常:Exception,事务也不会回滚。

spring 事务,默认情况只回滚 RuntimeException 和 Error,对于普通的 Exception(非运行时异常)不会进行回滚。

4 自定义了回滚异常

spring 通过 rollbackFor 参数,支持自定义回滚的异常。

但是,设置的是 BusinessException 异常,但是报错不属于其,比如是:SqlException 或其他的,事务也不会回滚。

虽然 rollbackFor 参数有默认值,但是阿里的规范手册中还是要求重新指定该参数。

rollbackFor 默认值为:UncheckedException,包括了 RuntimeException 和 Error,当知己使用 @Transcational 不指定 rollbackFor 时,Exception 及其子类都不会出发回滚。

所以,一般建议写成:@Transcational(rollBackFor = Exception.class)

5 嵌套事务回滚多了


发布于: 刚刚阅读数: 3
用户头像

阿婷

关注

还未添加个人签名 2022.08.22 加入

还未添加个人简介

评论

发布
暂无评论
Java基础知识总结--事务失效的12种场景_事务_阿婷_InfoQ写作社区