spring 中的事务 - Transactional 详细解析

分类

声明式事务

建立在aop之上的,我们常用的事务

声明式事务是编程式事务 + AOP 技术包装


编程式事务

基于pojo的事务,我们用的较少

我们需要在代码中显式调用 beginTransaction()、commit()、rollback() 等事务管理相关的方法,这就是编程式事务管理。



隔离级别 - isolation


类似于数据库中的事务隔离级别

通过设置Transactional的属性isolation 来设置


1、Isolation.DEFAULT

事务默认的隔离级别,使用数据库默认的隔离级别。


2、Isolation.READ_UNCOMMITTED

这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。

这种隔离级别会产生脏读,不可重复读和幻读。


3、Isolation.READ_COMMITTED

保证一个事务修改的数据提交后才能被另外一个事务读取。

另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻读。


4、Isolation.REPEATABLE_READ

这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。


5、Isolation.SERIALIZABLE

这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。



传播行为 - propagation

在SpringBoot中通过Transactional的propagation属性来指定

7种传播行为,常用的为前两种


1、REQUIRED

默认,如果调用者没有事务,则开启事务,如果调用者有事务,则加入该事务

例如:a调用b,如果a有事务,b回滚了,a也会回滚


2、REQUIRES_NEW

开启一个自己独立的事务,调用者有事务也会先挂起

例如:a调用b,a事务回滚,b不会回滚,但是b异常回滚了,a也会回滚


3、SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

用于非核心业务,即使报错也不需要回滚的代码(看调用者的事务必要性)。

例如:a调用b,a存在事务,b加入;如果a没有事务,b也以非事务方式执行。


4、NOT_SUPPORTED

以非事务方式运行,如果当前存在事务,则把当前事务挂起。

它可以帮助将事务极可能的缩小,因为一个事务越大,它存在的风险也就越多,所以在处理事务的过程中,要保证尽可能的缩小范围。

例如:a调用b,b中以非事物状态运行,b报错了,a事务也不会回滚


5、NEVER

以非事务方式运行,如果当前存在事务,则抛出抛出Runtime 异常,强制停止执行。

例如:a调用b,如果a有事务,直接抛出Runtime异常


6、MANDATORY

如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。也就是说,MANDATORY 要求上下文中必须要存在事务,否则就会抛出异常。

例如:a调用b,如果a没有事务,b直接抛异常


7、NESTED

如果当前存在事务,则创建一个事务作为当前事务的嵌套事务(子事务)来运行;如果当前没有事务,则该取值等价于 REQUIRED

例如:a调用b,a回滚,b也跟着你回滚,但是b回滚,不会影响a和其他子事务



其他属性

1、timeout

事务的超时时间,单位为秒


2、readOnly

该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false

如果一个事务只涉及到只读,可以设置为true


3、rollbackFor 属性

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型

默认是在RuntimeExceptionError上回滚


4、noRollbackFor

抛出指定的异常类型,不回滚事务,也可以指定多个异常类型



失效情况

我们讨论的是基于默认的事务传播级别:REQUIRED

1、mysql的数据库引擎是MyISAM

2、注解加的方法的访问修饰符不是public

3、事务中异常被捕捉处理,没有抛出

4、同类方法调用,a调用b方法,b方法事务失效

为什么此时事务失效?

其实原因很简单,Spring在扫描Bean的时候会自动为标注了@Transactional注解的类生成一个代理类(proxy),当有注解的方法被调用的时候,实际上是代理类调用的,代理类在调用之前会开启事务,执行事务的操作,但是同类中的方法互相调用,相当于this.B(),此时的B方法并非是代理类调用,而是直接通过原有的Bean直接调用,所以注解会失效。

5、如果使用了Spring + MVC,则 context:component-scan 重复扫描问题可能会引起事务失效



站在巨人的肩膀上学习和整理,如有纰漏,欢迎大家指出交流!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章