Spring事务及事务传播机制(2)

@Transactional详解

我们主要学习@Transactional注解当中的三个常见属性:

1.rollbackFor: 异常回滚特性. 指定能够触发事务回滚的异常类型. 可以指定多个异常类型.

2.Isolation:事务的隔离级别. 默认值为Isolation.DEFAULT

3.propagation: 事务的传播机制. 默认为Propagation.REQUIRED.

rollbackFor

@Transactional 默认只在遇到运行时异常和Error才会进行回滚, 非运行时异常不回滚. 即Exception的子类中, 除了RuntimeException及其子类.

之前我们通过制造一个运行时异常, 发现事务回滚了, 接下来把异常改为如下代码:

java 复制代码
    @Transactional
    @RequestMapping("/registry")
    public String registry(String name, String password) throws IOException {
        //用户注册
        userService.registryUser(name, password);
        log.info("用户数据插入成功");
        if(true) {
            throw new IOException();
        }
        return "注册成功";
    }

运行程序:

发现虽然程序抛出了异常, 但是事务仍被提交:

如果需要所有的异常都回滚, 需要配置@Transactional注解当中的rollbackFor属性, 通过rollbackFor这个属性指定出现何种异常类型时事务进行回滚.

java 复制代码
@Transactional(rollbackFor = Exception.class)

运行代码, 观察现象:

发现这时事务进行了回滚.

结论:

在Spring事务管理中, 默认只在遇到运行时异常RuntimeException和Error时才会进行回滚.

如果需要回滚指定类型的异常, 可以通过rollbackFor属性来指定.

事务隔离级别

回顾: 并发读数据库可能引发的问题

1.脏读:指一个事务A读取到了事务B还没有提交的数据, 在之后事务B进行了修改, 这时候事务A读到的数据称为脏数据, 也叫脏读.(解决方案: 给写操作加锁, 即一个事务在没有提交之前, 不能被读取).

2.不可重复读**: 一个事务先后两次读取到的数据不一致, 可能是两次读取过程中插入了一个新的事务更新了原有的数据, 注:侧重于修改**(解决方案: 给读操作加锁, 即一个事务在没有读完的时候不会插入其它的数据).

3.幻读: 同一个事务中, 多次查询的结果集返回不一致 . 比如事务A查询了几列数据, 而事务B在此时又插入了新的几列数据(注:侧重于新增或删除),先前的事务在接下来的查询中, 就会发现几列是它先前所没有的, 这就是幻读. (解决方案: 进一步提高事务之间的隔离性, 即串行化).

MySQL数据库事务隔离级别

1.读未提交: 最低的隔离级别, 在该级别内可以看到其它事务未提交的数据.

因为其它未提交的数据可能会发生回滚, 但是在该级别下仍然是可以读到的, 这个读到的就是脏数据.

2.读已提交: 在该级别内, 一个事务只能读取其它事务中已提交的数据(相当于加写锁).

在该隔离级别内不会存在脏读的问题. 但由于在事务的执行中可以读取到其它事务提交的结果, 所以在不同时间读取到的数据可能不一致.

3.可重复读: 事务不会读到其它事务对已有数据的修改, 即使其它事务已经提交. 也就可以确保同一事务多次查询到的结果一致, 但是对于其它事务新插入的数据, 是可以感知到的. 这就引发了幻读问题. 可重复读, 是MySQL中默认的事务隔离级别(相当于加读锁和写锁).

比如此级别的事务正在执行时, 另一个事务中新增了一条数据, 但是由于每次读取的时候结果都一样, 所以导致查询不到这条数据.

4.串行化: 是事务的最高隔离级别, 它会强制事务排序, 使之不会发生冲突. 但是因为资源消耗很大, 所以不太常用.

Spring中的事务隔离级别:

1.Isolation.DEFAULT: 以连接的数据库的隔离级别为主.

2.Isolation.READ_UNCOMMITTED:读未提交

3.Isolation.READ_COMMITED: 读已提交.

4.Isolation.REPEATABLE_READ: 可重复读

5.Isolation.SERIALIZABLE: 串行化.

spring中的事务隔离级别也可以通过类似之前的rollbackFor的方式设置:

java 复制代码
@Transactional(isolation = Isolation.READ_COMMITTED)

Spring事务传播机制

什么是事务传播机制

事务传播机制就是: 多个事务方法存在调用关系时, 事务是如何在这些方法间进行传播的.

比如有两个方法A, B都被@Transactional修饰, A方法调用B方法, 此时B方法运行时, 是加入A的事务, 还是创建一个新的事务呢?

这就涉及到了事务的传播机制.

事务隔离级别解决的是多个事务同时调用一个数据库的问题.

而事务传播机制解决的hi一个事务在多个节点(方法)中传递的问题

事务的传播机制有哪些?

@Transactional注解支持事务传播机制的设置, 通过propagation属性来指定传播行为.

Spring事务传播机制有以下7种(以下结合一对新人要结婚的例子来说明):

1.Propagation.REQUIRED: 默认的事务隔离级别. 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则创建一个新的事务.(需要有房子, 如果你有房, 我们就一起住, 如果你没房, 我们就一起买房).

2.Propagation.SUPPORTS: 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则继续以非事务的方式继续执行.(可以有房子, 如果你有房, 那就一起住, 如果没房, 那就租房).

3.Propagation.MANDATORY: 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则抛出异常.(必须有房子, 要求必须有房, 如果没房就不结婚).

4.Propagation.REQUIRES_NEW: 创建一个新的事务. 如果当前存在事务, 则把当前事务挂起.

(必须买新房, 不管你有没有房, 必须要两个人一起买房. 即使有房也不住)

5.Propagation.NOT_SUPPORTED: 以非事务的方式运行, 如果当前存在事务, 则把当前事务挂起. (不需要房, 不管你有没有房, 我都不住, 必须租房)

6,Propagation.NEVER: 以非事务的方式运行, 如果当前存在事务, 则抛出异常(不能有房子)

7.Propagation.NESTED: 如果当前存在事务, 则创建一个事务作为当前事务的嵌套事务运行, 如果没有事务, 则取值等价于Propagation.REQUIRED.(如果有房, 则以房子为根据地, 做点下生意.)

相关推荐
阿维的博客日记9 分钟前
图文并茂解释水平分表,垂直分表,水平分库,垂直分库
数据库·分库分表
秋落风声41 分钟前
【数据结构】---图
java·数据结构··graph
2401_8576226643 分钟前
Spring Boot新闻推荐系统:性能优化策略
java·spring boot·后端
qinzechen1 小时前
分享几个做题网站------学习网------工具网;
java·c语言·c++·python·c#
hakesashou1 小时前
python交互式命令时如何清除
java·前端·python
攒了一袋星辰1 小时前
今日指数项目项目集成RabbitMQ与CaffienCatch
java·分布式·rabbitmq
wrx繁星点点1 小时前
事务的四大特性(ACID)
java·开发语言·数据库
IT学长编程1 小时前
计算机毕业设计 Java酷听音乐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·音乐系统·计算机毕业设计选题
AskHarries1 小时前
如何优雅的处理NPE问题?
java·spring boot·后端
IT学长编程2 小时前
计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·毕业论文·协同过滤算法·计算机毕业设计选题·个性化音乐推荐系统