博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring Transcation事务的学习
阅读量:6533 次
发布时间:2019-06-24

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

hot3.png

大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销。Spring事务管理基于底层数据库本身的事务处理机制。数据库事务的基础,是掌握Spring事务管理的基础。这篇总结下Spring事务。

事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写‘’

  1. 原子性(Atomicity)事务最基本的操作单元,要么全部成功,要么全部失败,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
  2. 一致性(Consistency)事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。
  3. 隔离性(Isolation)指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
  4. 持久性(Durability)指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

spring事务管理机制

spring事务依赖的jar包是 Spring framework

spring事务管理高层抽象主要包括3个接口,spring的事务主要是由他们共同完成的:

1.PlatformTranscationManager:事务管理器-主要用于平台相关事务的管理

2.TranscationDefinition:事务定义信息(隔离,传播,超时,只读)-通过配置如何进行事务管理

3.TranscationStatus:事务具体运行状态-事务管理过程中,每个时间点事务的状态信息

三个接口之间的关系:

1.如果用户需要通过spring管理实务,就需要先配置不同的TranscationManager(不同的持久层框架,有不同的事务管理器实现类)

2.然后根据TranscationDefinition(实务定义信息),通过TranscationManager进行事务管理。

3.最后事务在运行过程中,每个时刻都通过TranscationStatus(事务状态)来了解事务运行状态。

1.1 PlatformTranscationManager事务管理器

PlatformTranscationManager是一个顶层接口,它定义了三个方法:

void commit(); 提交事务

void rollback(); 回滚事务

TranscationStatus getTranscationStatus(); 获取事务状态

spring为不同的持久化层框架提供了不同的PlatformTranscationManager接口实现类:

a778160c5449cb94f6b318cf0c38b3bc65d.jpg

DataSourceTranscationManager针对JdbcTemplate,MyBatis事务控制,使用connection(连接)进行事务控制:

开启事务:connection.setAutoCommite(false);   // 关闭自动提交

提交事务:connection.commit();

回滚事务:connection.rollback();

 

1.2 TranscationDefinition事务的定义信息

TranscationDefinition也是一个接口,它拥有的方法:

int getIsolationLevel(); // 获取事务隔离等级

String getName(); // 返回当前事务名称

int getPropagationBehavior(); // 返回传播行为

int getTimeout(); // 获取超时时间,默认是-1 不超时

boolean isReadOnly(); // 是否只读

这些事务的定义信息,可以通过配置文件来定制

1.2.1 常用事务的隔离级别 isolationLevel

隔离级别                                           意义

DEFAULT                                         使用选用的数据库的默认的隔离级别(spring中的选择项)

                                                        注意:不同厂商的数据库,默认的事务隔离等级也是不一样的,比如oracle默认的是READ_COMMITED,mysql默认的                                                          隔离级别是:REPEATABLE_READ

READ_UNCOMMITED                     允许读取还未提交的数据,可能导致脏读,幻读、不可重复读

READ_COMMITED                          允许在并发事务已经提交后读取,可防止脏读,但是可能会幻读、不可重复读

REPEATABLE_READ                         对相同数据的多次读取结果是一致的,除非数据被当前事务改变。可防止脏读、不可重复读,但是幻读仍会发生。

SERIALIZABLE                                 完全服从ACID的隔离级别,确保不发生脏读,幻读,不可重复读。这在所有事务级别中是最慢的,它是通过完全锁定事                                                         务中数据所涉及的表来实现的

 

这里,我们解释一下脏读,不可重复读,幻读:

脏读:一个事务读取了另一个事务还未提交的数据,如果这些数据被回滚了,那读取到的数据是无效的。

不可重读:在同一个事务中,多次读取同一数据,返回的结果不同。意味着后面读取到的数据,是另一个事务提交后的数据。

可重复读:在同一个事务中,多次读取同一数据,能够保证读取到的结果是一样的,也就是后续读取数据不会读取到其他事务提交后的数据。

幻读:一个事物读取了几行记录后,另一个事务插入了一些新纪录,再后来的查询中,第一个事物读取到了之前没有的记录,这就发生了幻读。

 

1.2.2 PropagationBehavior事务的传播行为

什么是事务的传播行为?有什么作用?

事物的传播行为,用于解决两个被事务管理的方法之间互相调用的问题。

业务层中有两个方法,有些时候需要两个方法处于同一个事务中,有些时候又需要两个方法不能在同一个事务中。

事务传播行为的7种类型

事务传播行为类型                                                  说明

PROPAGATION_REQUIRED                                  支持当前事务,如果不存在,就新建一个

PROPAGATION_SUPPORTS                                  支持当前事务,如果不存在,就不使用事务

PROPAGATION_MANDATORY                             支持当前事务,如果不存在,抛出异常

PROPAGATION_REQUIRES_NEW                         如果有事务存在,挂起当前事务,创建一个新事物

PROPAGATION_NOT_SUPPORTS                         以非事务方式运行,如果有当前事务,挂起当前事务

PROPAGATION_NEVER                                         以非事务方式运行,如果有当前事务,抛出异常

PROPAGATION_NESTED                                       如果当前事务存在,则嵌套事务执行,只对DataSourcePlatformTranscationManager起效

 

主要分为三大类:

PROPAGATION_REQUIRED(默认),PROPAGATION_SUPPORTS,PROPAGATION_MANDATORY

支持当前事务,A调用B,如果A有事务存在,B和A处于同一个事务,一起提交或一起回滚。

事务的默认传播行为,PROPAGATION_REQUIRED,最常用

 

PROPAGATION_REQUIRES_NEW,PROPAGATION_NOT_SUPPORTS,PORPAGATION_NEVER

不支持当前事务,A调用B,如果A有事务存在,B肯定不会和A处在同一事务

常用的事务传播行为,PORPAGATION_REQUIRES_NEW

 

PORPAGATION_NESTED

嵌套事务,只对DataSourcePlatformTranscationManager有效,底层使用JDBC的Savepoint机制,允许在同一个事务设置保存点,回滚到保存点。

 

REQUIRED,REQUIRES_NEW,NESTED的区别:

REQUIRED:支持当前事务,不存在事务,创建新事务

REQUIRES_NEW:不支持当前事务,如果存在事务,挂起当前事务,创建新事物

NESTED:嵌套事务,事务可以设置保存点,回滚到保存点

 

1.3 TranscationStatus事务状态

TranscationStatus也是一个接口,它含有一下方法:

void flush();      // 发送,执行SQL语句

boolean hasSavepoint();  // 是否有保留点

boolean isCompleted();  // 执行完了没有

boolean isNewTranscation();  // 是否是新建的事务

boolean siRollbackOnly();   // 判断是否为只能回滚的事务,通常用于进行测试,不希望测试操作真的操作到数据库

void setRollbackOnly(); // 设置事务是否回滚

 

事务的结束:必须通过commit确认事务的提交,rollback作用是标记为回滚,比如回滚到未操作的时候。

try{

    操作数据库

}catch(){

    // 如果发生异常了,我们回滚到未操作的时候

    rollback();

}finally{

    // 执行完毕,提交

    commit;

}

1.4spring事务管理方式

两种方式:

1.编程式的事务管理

通过TranscationTemplate手动管理事务。

在实际开发中很少用到,原因是需要修改原有代码,加入事务控制代码(侵入性)

1640e068d723f845d675e516660c16afdc9.jpg

2.通过xml配置文件或者在类中添加注解的方式

spring的声明式事务是通过AOP实现的(环绕通知)

方法执行前,开启事务,方法执行后,关闭事务。

 

Spring如何配置事务

2.1 xml配置方式添加事务管理(tx事务,aop切面)

操作思路:AOP三步走

1.确定目标:需要对service层的方法,配置切入点

2.需要配置Adivce(环绕通知),方法执行前开启事务,方法执行后关闭事务

3.配置切面和切入点

 

38dc73bc875372b6fe073a64f5ec6dcc997.jpg

在spring的配置文件中,我们首先引入数据源的配置文件,然后通过数据源驱动类,创建dataSource,指定数据源的驱动类名称,url,用户名,密码。

05105a1c2601b7f808741c7afe0ca5ee719.jpg

d6889355a22de32362f7a0cfe026f69337f.jpg

然后呢,我们通过dataSource,来配置事务管理器,

f1f56f9d4f3b05947bc7cdcc34c16b8b3ca.jpg

配置事务通知

3d9c7d2a7bd46667fb3beff99f0eb2091b7.jpg

 transfer是service层中一个业务方法的名称。

rollback-for就是指定一个地方,当事务要回滚的时候,可以指定事务只回滚到rollback-for这里。

配置切入点和切面

34fe511066ff643e625f8af06f064af476e.jpg

其中expression是表达式,bean(*service)表达所有配置文件中,id或者name为service结尾的bean

配置的dao层和service层

cd95b581cac5b32c6db738271a30e341b42.jpg

2.2 基于注解的方式实现事务管理

annotations

spring的配置文件中,可以不用再配置service,dao的bean和事务通知,AOP的bean了。因为它们会在项目中基于注解实现。

反之,需要配置 注解扫描,并制定扫描的包,确保可以扫描到注解

623b98f015e1980cd3d0130aa2064e1b490.jpg

基于注解的方式配置事务,还需要配置事务相关的注解驱动

ccf643e2a6c4fd5654254e372adefa10963.jpg

e905f017626369b2ae9d54f2efd25a49d82.jpg

再给需要事务的方法,加上事务的注解

59b5d2cfc5eec29f1d5f7024df2ff75e9c6.jpg

虽然执行会报错,但是因为被事务管理了,报错后发生了回滚,数据库的数据不会改变。

@Transactional注解,可以针对方法去加,只对方法进行管理,也可以加到类上,对整个类进行事务管理

那事务的隔离级别,传播行为怎么控制?

139c7deb6e248745408772974d516ed1cfb.jpg

ReadyOnly属性,设置为false,说明该事务会对数据库进行增删改操作,设置为true,说明该事务只对数据库进行查的操作。

timeout默认设置为-1,意思是不超时。

f688a816f0a8d9220bfd912effda8b94d2a.jpg

就近原则,当方法上的注解和类上的注解冲突后,优先以方法上的注解为准。

杂记

  1. 事务属性这个概念,事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成。这些属性都是在使用@Transactional可以指定的。
  2. 底层原理:Spring事务其实就是Spring AOP,底层创建动态代理对象,在代码的开头结尾封装了开启事务和事务回滚操作。用过JDBC原生代码的更应该清楚了,都是显示在代理里commit和rollback的。然后一大堆try catch。
  3. 在service类前加上,声明这个service所有方法需要事务管理。每一个业务方法开始时都会打开一个事务。或者加在service层方法上,@Transactional只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能..

转载于:https://my.oschina.net/xiaoyoung/blog/3042028

你可能感兴趣的文章
操作系统---进程 vs 线程
查看>>
Java 学习(18)--列表(List)/ 集合 (Set)/ 泛型 / Map
查看>>
Linux内核-协议栈-从BSD Socket接口层到传输层1
查看>>
两款测试管理工具:TestLink 与飞蛾深度横评
查看>>
如何查看 Linux 中所有正在运行的服务
查看>>
戴尔大中华区解决方案顾问鲍荣钦:技术驱动,数据改变物流
查看>>
apache做反向代理服务器
查看>>
Android应用性能测试
查看>>
修复垂直滑动RecyclerView嵌套水平滑动RecyclerView水平滑动不灵敏问题
查看>>
使用序列化快速读写XML文件
查看>>
bootstrap-胶囊式标签页
查看>>
webstorm intelliJ IDEA phpstorm 设置鼠标滚动改变字体大小
查看>>
对内存对齐的深一步理解
查看>>
java-第八章-幸运抽奖-实现循环执行功能
查看>>
Synchronized及其实现原理
查看>>
Excel碰到空行无法筛选排序解决方法
查看>>
内容超出表格<td>宽度则自动隐藏
查看>>
EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
查看>>
进程终结
查看>>
Redisson官方文档 - 10. 额外功能
查看>>