博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring系列之事物
阅读量:2240 次
发布时间:2019-05-09

本文共 5425 字,大约阅读时间需要 18 分钟。

本节任务:

1、用事物(基本用法;传播机制;隔离级别)

2、事物的原理

 

spring的事物是通过AOP来实现的。

spring事物的配置:

事物简介:

事物是访问数据库一些数据的一个程序执行单元,是数据恢复和并发控制的基本单位。

事物的四大特性:原子性,一致性,隔离性,持久性;通常成为ACID。

原子性(Automicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都成功提交,要么都失败回滚;要么全                                          部成功,要么全部失败。 

一致性(Consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。 一致性与原子性是密切相关的(像同                                           行转账,转来转去银行的总金额是不变的)。 
隔离性(Isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,                                      并发执行的各个事务之间不能互相干扰。
持久性(Durability)。持久性也称永久性(Permanence),指一个事务一旦提交,它 对数据库中数据的改变就应该是永久性                                         的。接下来的其他操作或故障不应该对其有任何 影响。

 

前朝旧事:JDBC操作数据库的步骤:

1、创建连接Connection con = DriverManager.getConnection()

2、开启事物con.setAutoCommit(true/false);

3、业务操作(crud)

4、成功提交\失败回滚con.commit() / con.rollback();

5、关闭连接conn.close();

spring事物就是解决了第2步和第4步。

spring注解实现事物操作:

配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional 标识。 Spring 在启动的时候会去解析生成相关的 bean,这时候会查看拥有相关注解的类和方 法,并且为这些类和方法生成代理,并根据@Transaction 的相关参数进行相关配置注入, 这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。 真正的数据库层的事务提交和回滚是通过 binlog 或者 redo log 实现的。


spring事物的传播机制

传播机制解决的是多个事物同时存在的时候的行为。

传播机制 解释
PROPAGATION_
REQUIRED
支持当前事务,如果当前没有事务,就新建 一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。
PROPAGATION_
REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务 挂起。新建的事务将和被挂起的事务没有任 何关系,是两个独立的事务,外层事务失败 回滚之后,不能回滚内层事务执行的结果, 内层事务失败抛出异常,外层事务捕获,也 可以不处理回滚操作
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事 务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按
REQUIRED 属性执行。它使用了一个单独的 事务,这个事务拥有多个可以回滚的保存 点。内部事务的回滚不会对外部事务造成影 响。它只对 DataSourceTransactionManager 事务管 理器起效。

 

 

 

 

 

 

 

 

 

 

 

 

在传播机制下的spring嵌套事务(假设外层事务 Service A 的 Method A() 调用 内层 Service B 的 Method B()

传播机制 场景在线
PROPAGATION_REQUIRED(Spring 默认)
如果 ServiceB.MethodB() 的事务级别定义为 ROPAGATION_REQUIRED,那么执行 ServiceA.MethodA() 的时候 Spring 已经起了事务,这时调用 ServiceB.MethodB(),
ServiceB.MethodB() 看到自己已经运行在 ServiceA.MethodA() 的事务内部,就不再 起新的事务。
假如 ServiceB.MethodB() 运行的时候发现自己没有在事务中,他就会为自己分配一个 事务。
这样,在 ServiceA.MethodA() 或者在 ServiceB.MethodB() 内的任何地方出现异常, 事务都会被回滚。
PROPAGATION_REQUIRES_NEW
ServiceA.MethodA() 的事务级别为 PROPAGATION_REQUIRED,
ServiceB.MethodB() 的事务级别为 PROPAGATION_REQUIRES_NEW。
那么当执行到 ServiceB.MethodB() 的时候,ServiceA.MethodA() 所在的事务就会挂 起,ServiceB.MethodB() 会起一个新的事务,等待 ServiceB.MethodB() 的事务完成 以后,它才继续执行。
他 与 PROPAGATION_REQUIRED 的 事 务 区 别 在 于 事 务 的 回 滚 程 度 了 。 因 为 ServiceB.MethodB() 是 新 起 一 个 事 务 , 那 么 就 是 存 在 两 个 不 同 的 事 务 。 如 果 ServiceB.MethodB() 已 经 提 交 , 那 么 ServiceA.MethodA() 失 败 回 滚 ,ServiceB.MethodB() 是不会回滚的。如果 ServiceB.MethodB() 失败回滚,如果他抛出的异常被 ServiceA.MethodA() 捕获,ServiceA.MethodA() 事务仍然可能提交(主要
看 B 抛出的异常是不是 A 会回滚的异常)。
PROPAGATION_SUPPORTS
假设 ServiceB.MethodB() 的事务级别为 PROPAGATION_SUPPORTS,那么当执行到 ServiceB.MethodB()时,如果发现 ServiceA.MethodA()已经开启了一个事务,则加入 当前的事务,如果发现 ServiceA.MethodA()没有开启事务,则自己也不开启事务。这种 时候,内部方法的事务性完全依赖于最外层的事务。
PROPAGATION_NESTED
现 在 的 情 况 就 变 得 比 较 复 杂 了 , ServiceB.MethodB() 的 事 务 属 性 被 配 置 为 PROPAGATION_NESTED, 此时两者之间又将如何协作呢? ServiceB.MethodB() 如 果 rollback, 那么内部事务(即 ServiceB.MethodB()) 将回滚到它执行前的 SavePoint 而外部事务(即 ServiceA.MethodA()) 可以有以下两种处理方式:1、 捕获异常,执行异常分支逻辑这 种 方 式 也 是 嵌 套 事 务 最 有 价 值 的 地 方 , 它 起 到 了 分 支 执 行 的 效 果 , 如 果
ServiceB.MethodB()失败, 那么执行 ServiceC.MethodC(), 而 ServiceB.MethodB() 已经回滚到它执行之前的 SavePoint, 所以不会产生脏数据(相当于此方法从未执行过), 这 种 特 性 可 以 用 在 某 些 特 殊 的 业 务 中 , 而 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRES_NEW 都没有办法做到这一点。2、
外部事务回滚/提交 代码不做任何修改
, 那么如果内部事务(ServiceB.MethodB()) rollback, 那么首先 ServiceB.MethodB() 回滚到它执行之前的 SavePoint(在任何情况 下都会如此), 外部事务(即 ServiceA.MethodA()) 将根据具体的配置决定自己是 commit 还是 rollback。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

spring事物的隔离级别:

常量 解说
ISOLATION_DEFAULT
这是个 PlatfromTransactionManager 默 认的隔离级别,使用数据库默认的事务隔离
级别。另外四个与 JDBC 的隔离级别相对 应。
ISOLATION_READ_UNCOMMITTED
这是事务最低的隔离级别,它允许另外一个 事务可以看到这个事务未提交的数据。这种
隔离级别会产生脏读,不可重复读和幻像 读。
ISOLATION_READ_COMMITTED
保证一个事务修改的数据提交后才能被另 外一个事务读取。另外一个事务不能读取该
事务未提交的数据。
ISOLATION_REPEATABLE_READ
这种事务隔离级别可以防止脏读,不可重复 读。但是可能出现幻像读。
ISOLATION_SERIALIZABLE
这是花费最高代价但是最可靠的事务隔离 级别。事务被处理为顺序执行。

 

 

 

 

 

 

 

事物的隔离级别

隔离级别 隔离级别的值 导致的问题
Read-Uncommitted
0
导致脏读
Read-Committed
1
避免脏读,允许不可重复读和幻读
Repeatable-Read
2
避免脏读,不可重复读。允许幻读
Serializable
3
串行化读,事务只能一个一个执行,避免了 脏读、不可重复读、幻读。执行效率慢,使 用时慎重

 

 

 

 

 

 

 

脏读
:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如 果第一个事务这时候回滚了,那么第二个 事务就读到了脏数据。
 
不可重复读
:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一 个事务对数据进行了修改,这时候两次读取的
同一条
数据是不一致的。
 
幻读
:读取的
条数
不一致。第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数 据,这时候第一个事务就会丢失对新增数据的修改。

 

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle
少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB

 

使用模板操作数据库的几种方式:

1、JdbcTemplate - 这是经典的也是最常用的 Spring 对于 JDBC 访问的方案。这也是最低 级别的封装, 其他的工作模式事实上在底层使用了 JdbcTemplate 作为其底层的实现基 础。JdbcTemplate 在 JDK 1.4 以上的环境上工作得很好。

2、NamedParameterJdbcTemplate - 对 JdbcTemplate 做了封装,提供了更加便捷的基 于命名参数的使用方式而不是传统的 JDBC 所使用的“?”作为参数的占位符。这种方式 在你需要为某个 SQL 指定许多个参数时,显得更加直观而易用。该特性必须工作在 JDK 1.4 以上。

3、SimpleJdbcTemplate - 这 个 类 结 合 了 JdbcTemplate 和 NamedParameterJdbcTemplate 的最常用的功能,同时它也利用了一些 Java 5 的特性 所带来的优势,例如泛型、varargs 和 autoboxing 等,从而提供了更加简便的 API 访问 方式。需要工作在 Java 5 以上的环境中。

4、SimpleJdbcInsert SimpleJdbcCall - 这两个类可以充分利用数据库元数据的特性 来简化配置。通过使用这两个类进行编程,你可以仅仅提供数据库表名或者存储过程的 名称以及一个 Map 作为参数。其中 Map 的 key 需要与数据库表中的字段保持一致。这 两个类通常和 SimpleJdbcTemplate 配合使用。这两个类需要工作在 JDK 5 以上,同时 数据库需要提供足够的元数据信息。

5、RDBMS 对象包括 MappingSqlQuery, SqlUpdate and StoredProcedure - 这种方式 允许你在初始化你的数据访问层时创建可重用并且线程安全的对象。该对象在你定义了 你的查询语句,声明查询参数并编译相应的 Query 之后被模型化。一旦模型化完成,任 何执行函数就可以传入不同的参数对之进行多次调用。这种方式需要工作在 JDK 1.4 以 上。

 

spring 事物原理分析

(待续)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载地址:http://bcqbb.baihongyu.com/

你可能感兴趣的文章
详解循环神经网络(Recurrent Neural Network)
查看>>
为什么要用交叉验证
查看>>
用学习曲线 learning curve 来判别过拟合问题
查看>>
用验证曲线 validation curve 选择超参数
查看>>
用 Grid Search 对 SVM 进行调参
查看>>
用 Pipeline 将训练集参数重复应用到测试集
查看>>
PCA 的数学原理和可视化效果
查看>>
机器学习中常用评估指标汇总
查看>>
什么是 ROC AUC
查看>>
Bagging 简述
查看>>
详解 Stacking 的 python 实现
查看>>
简述极大似然估计
查看>>
用线性判别分析 LDA 降维
查看>>
用 Doc2Vec 得到文档/段落/句子的向量表达
查看>>
使聊天机器人具有个性
查看>>
使聊天机器人的对话更有营养
查看>>
一个 tflearn 情感分析小例子
查看>>
attention 机制入门
查看>>
手把手用 IntelliJ IDEA 和 SBT 创建 scala 项目
查看>>
GAN 的 keras 实现
查看>>