Spring事务及事务传播机制

目录

一、什么是事务

二、事务的操作

三、Spring下实现事务

1、Spring编程式事务

(1)事务提交

(2)事务回滚

2、Spring声明式事务

(1)无异常--提交

(2)异常且不捕获--回滚

(3)异常且捕获--提交

四、异常捕获后进行回滚

1、再次抛异常--回滚

2、手动进行回滚--回滚

五、@Transactional注解常见三个属性

1、rollbackFor

2、Isolation

3、propagation

一、什么是事务

事务是一个不可分割的操作。事务会把一些列操作看做一个整体提交给数据库,要么全部执行成功,要么出现异常全部撤回不执行。例如:A向B转100元,此时A账号-100,B账号+100,修改数据库时,对这两个操作就要求要求全部成功或全部失败。

二、事务的操作

开启事务、提交事务(全部成功)、回滚事务(全部失败)。

三、Spring下实现事务

用户表注册账号,使用事务实现。准备工作:用户表、实体类、建立数据库连接。

1、Spring编程式事务
(1)事务提交

DataSourceTransactionManager:事务管理器,用来获取事务(getTransaction)、提交事务(commit)、回滚事务(rollback);

TransactionDefinition:是事务的属性,在获取事务的时候,需作为参数,从而获取到一个事务;

TransactionStatus:事务的状态,提交和回滚。

当事务是提交时,数据库插入成功。

(2)事务回滚

事务进行了回滚,虽然提醒插入成功,但数据库没有插入的结果。

2、Spring声明式事务

以上需要获取事务、提交事务、回滚事务,比较繁琐。当加上@Transactional注解之后,就自动获取事务,没有异常或异常已进行捕获自动提交事务,有异常且未进行捕获就回滚事务。

(1)无异常--提交

(2)异常且不捕获--回滚

事务进行了回滚,虽然提醒插入成功,但数据库没有插入的结果。

(3)异常且捕获--提交

四、异常捕获后进行回滚

上述出现异常后,如若进行了捕获,事务还是会提交。如何在异常捕获后进行事务回滚???

1、再次抛异常--回滚

2、手动进行回滚--回滚

五、@Transactional注解常见三个属性

1、rollbackFor

rollbackFor:异常回滚属性,指定能够触发事务回滚的异常类型,可以指定多个异常类型。

@Transactional注解默认只有运行时异常和Error时才会进行回滚,其他异常不会回滚。

例如:

以上代码在运行时会抛出IOException异常,但事务依旧会提交,因为不是运行时异常。

若想所有异常都进行回滚,可以设置rollbackFor属性:

2、Isolation

Isolation:事务隔离级别。

(1)之前学习mysql的隔离级别:

①读未提交(可能出现脏读);②读提交(不可重复读);③可重复读(可能出现幻读)--mysql默认隔离级别;④串行化读。

(2)@Transactional注解的隔离级别:

①Isolation.DEFAULT:以连接的数据库的事务隔离级别为主;

②Isolation.READ_UNCOMMITTED:读未提交,可能出现脏读;

③Isolation.READ_COMMITTED:读已提交,不可重复读;

④Isolation.REPEATABLE_READ:可重复读,可能出现幻读;

⑤Isolation.SERIALIZABLE:串行化读。

(3)设置@Transactional注解的Isolation属性

3、propagation

propagation:事务的传播机制。

多个事务之间存在调用关系,事务如何进行传播的???

(1)Spring事务传播机制有7种:

Propagation.REQUTRED:默认的事务传播机制,如果当前外部方法存在该事务,则内部方法加入该事务,如果当前外部方法没有事务,则内部方法创建一个新的事务。

例如:A方法中调用了B,若A方法有事务,则B不创建事务;若A方法没有事务,则B创建事务。若B中的某一个方法出现异常,则B的所有事务都回滚。

Propagation.SUPPORTS:如果当前外部方法存在事务,则内部方法加入该事务;如果当前外部方法没有事务,则内部方法以非事务的方式继续运行。

例如:A方法中调用了B,若A方法有事务,则B不创建事务;若A方法没有事务,则B以非事务方式运行。若A存在事务且B中的一个方法出现异常,则B的所有事务都回滚。

Propagation.MANDATORY:如果当前外部方法存在事务,则内部方法加入该事务;如果当前外部方法没有事务,则内部方法抛出异常。

例如:A方法中调用了B,若A方法有事务,则B不创建事务;若A方法没有事务,则抛出异常。

Propagation.REQUIRES_NEW:无论外部方法是否存在事务,内部方法都会创建新的事务。且创建的事务之间互不打扰。

例如:A方法中调用了B,无论A是否有事务,B都会创建新的事务。

Propagation.NOT_SUPPORTED:无论外部方法和内部方法是否存在事务,都将事务挂起,以非事务方式运行。

例如:A方法中调用了B,无论A和B是否有事务,最终都以非事务运行。

Propagation.NEVER:以非事务方式运行,若外部或内部方法存在事务,则抛出异常。

例如:A方法中调用了B,若A或B存在事务,则抛出异常。

Propagation.NESTED:若外部方法存在事务,则内部方法创建一个事务作为当前事务的嵌套事务来运行;如果当前外部方法没有事务,则内部方法创建一个新的事务。

(2)Propagation.REQUTRED和Propagation.NESTED的区别

共同点:若事务全部执行成功,二者没有区别;

不同点:若有部分事务抛出异常,Propagation.REQUTRED是加入外部方法的事务,会导致事务全部回滚;Propagation.NESTED嵌套事务,只会有部分回滚。嵌套事务进入之后相当于新建了一个保存点,而回滚时只回滚到当前保存点。

(3)设置@Transactional注解的propagation属性

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ambition…

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值