spring中的事务到底是什么
spring事务
事务在代码里或者数据库中都可以配置。
其含义理解为 一系列的数据操作,要么全部执行完成、要么都不执行。归纳为
1、原子性:事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
2、一致性:一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败
3、隔离性:事务之间应该隔离开来。因为可能有许多事务会同时处理相同的数据,每个事务都应该与其他事务有隔离策略。
4、持久性:一旦事务完成,它的结果不会收到影响。通常情况下,事务的结果被写到持久化存储器中。
spring事务的配置方式
spring 在事务处理上支持编程式事务和声明式事务
1. 编程式事务管理
编程式事务管理是侵入性事务管理,使用TransactionTemplate或者直接使用PlatformTransactionManager,对于编程式事务管理,Spring推荐使用TransactionTemplate。
2. 声明式事务管理
声明式事务管理建立在AOP之上,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚。
编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的,而声明式事务不同,声明式事务属于无侵入式,不会影响业务逻辑的实现,只需要在配置文件中做相关的事务规则声明或者通过注解的方式,便可以将事务规则应用到业务逻辑中。
显然声明式事务管理要优于编程式事务管理,这正是Spring倡导的非侵入式的编程方式。唯一不足的地方就是声明式事务管理的粒度是方法级别,而编程式事务管理是可以到代码块的,但是可以通过提取方法的方式完成声明式事务管理的配置。
事务的传播机制
事务的传播性一般用在事务嵌套的场景,比如一个事务方法里面调用了另外一个事务方法,那么两个方法是各自作为独立的方法提交还是内层的事务合并到外层的事务一起提交,这就是需要事务传播机制的配置来确定怎么样执行。
这些属性在TransactionDefinition接口中定义,常用事务传播规则如下:
常量名称 | 含义 |
---|---|
PROPAGATION_REQUIRED | Spring默认的传播机制,如果外层有事务,则当前事务加入到外层事务,一块提交,一块回滚。如果外层没有事务,新建一个事务执行 |
PROPAGATION_REQUES_NEW | 1、该事务传播机制是每次都会新开启一个事务,同时把外层事务挂起,当当前事务执行完毕,恢复上层事务的执行。2、如果外层没有事务,执行当前新开启的事务。注意的是。新事物和挂起的事务是两个独立的事务。外层事务失败回滚不会导致内层事务回滚,内层事务失败回滚抛出异常,外层也可以不处理。 |
PROPAGATION_SUPPORT | 如果外层有事务,则加入外层事务,如果外层没有事务,则直接使用非事务方式执行。简称:完全依赖外层的事务 |
PROPAGATION_NOT_SUPPORT | 该传播机制不支持事务,如果外层存在事务则挂起,执行完当前代码,则恢复外层事务,无论是否异常都不会回滚当前的代码 |
PROPAGATION_NEVER | 该传播机制不支持外层事务,即如果外层有事务就抛出异常 |
PROPAGATION_MANDATORY | 与NEVER相反,如果外层没有事务,则抛出异常 |
PROPAGATION_NESTED | 该传播机制的特点是可以保存状态保存点,当前事务回滚到某一个点,从而避免所有的嵌套事务都回滚,即各自回滚各自的,如果子事务没有把异常吃掉,基本还是会引起全部回滚的。 |
使用注解@Transactional 定义事务传播机制:
@Transactional(propagation = Propagation.REQUIRED)
propagation属性值还可以取:
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
NEVER(TransactionDefinition.PROPAGATION_NEVER),
NESTED(TransactionDefinition.PROPAGATION_NESTED);
思考:在同一个类中,没有被声明事务的方法A 去调用有事务的方法B,但B中出现异常,那么事务B会回滚吗?
@Testpublic void test(){update();}@Transactionalpublic void update(){Blog blog=mapper.selectById(1);//原先是 测试blog.setTitle("事务测试");blog.setType(1);mapper.updateById(blog);int i=1/0;}
执行test方法,update方法中报异常,但发现事务并没有回滚。
发现数据还是更改了
这是为什么呢?
Spring事务管理用的是AOP,AOP底层用的是动态代理。所以如果我们在类或者方法上标注注解@Transactional
,那么会生成一个代理对象 proxy。
我们执行的也是代理对象中的tes() 方法,但是test方法中 的update()方法还是指向代理之前的update方法。而不是代理后被事务管理的update方法。
所以此时 没有事务的参与。
如果说,在不同类中,A方法调用 有事务管理的B,那么B中发生异常,是可以回滚的。
事务的隔离级别及产生的问题
隔离级别
在理想状态下,事务之间将完全隔离,从而可以防止这些问题发生。然而,完全隔离会影响性能,因为隔离经常涉及到锁定在数据库中的记录(甚至有时是锁
表)。完全隔离要求事务相互等待来完成工作,会阻碍并发。因此,可以根据业务场景选择不同的隔离级别。
事务的隔离级别有以下几种:
数据库隔离级别 | spring 中属性值 | 含义 |
---|---|---|
ISOLATION_DEFAULT | 使用后端数据库的默认隔离级别 | |
Read Uncommitted | ISOLATION_READ_UNCOMMITTED | (读取未提交内容)允许读取尚未提交的更改。可能导致脏读、幻读或不可重复读。 |
Read Committed | ISOLATION_READ_COMMITTED | (读取提交内容)(Oracle 默认级别)允许从已经提交的并发事务读取。可防止脏读,但幻读和不可重复读仍可能会发生。 |
Repeatable Read | ISOLATION_REPEATABLE_READ | (可重读)(MYSQL默认级别)对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻读仍可能发生。 |
Serializable | ISOLATION_SERIALIZABLE | (可串行化)这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。 |
产生的问题
1、脏读现象
脏读发生在一个事务读取了被另一个事务改写但尚未提交的数据时。如果这些改变在稍后被回滚了,那么第一个事务读取的数据就会是无效的、错误的。
2、不可重复读现象
一个事务执行两次重复的读取,两次读取的数据都不一样,这通常是另一个事务并发的改变了数据(不是回滚产生的改变数据)
主要指数据发生修改
3、幻读
一个事务A读取数据时/后,另一个事务B插入/删除了一些数据,下次事务A读取事务时,就会发现比第一次多/少了值。
回滚规则
在默认设置下,事务只在出现运行时异常(runtime exception)时回滚,而在出现受检查异常(checked exception)时不回滚(这一行为和EJB中的回滚行为是一致的)。
不过,可以声明在出现特定受检查异常时像运行时异常一样回滚。同样,也可以声明一个事务在出现特定的异常时不回滚,即使特定的异常是运行时异常。
Spring声明式事务配置参考
事物配置中有哪些属性可以配置?以下只是简单的使用参考
- 事务的传播性:
@Transactional(propagation=Propagation.REQUIRED) - 事务的隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
- 只读:
@Transactional(readOnly=true)
该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。 - 事务的超时性:
@Transactional(timeout=30) - 回滚:
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。
spring中的事务到底是什么相关推荐
- Spring中的事务控制
Chapter 1. Spring中的事务控制(Transacion Management with Spring) Table of Contents 1.1. 有关事务(Transaction)的 ...
- Spring中的事务控制学习中
Chapter 1. Spring中的事务控制(Transacion Management with Spring) Table of Contents 事务管理(Transaction Manage ...
- Spring中的事务管理详解
在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...
- spring中的事务配置
为什么80%的码农都做不了架构师?>>> 一 简介 spring中提供了三种事务管理的方法. 编程式事务管理 :亦即自己编写事务管理的代码,通过注入获取到spring中的事务管 ...
- Spring(四)——AOP、Spring实现AOP、Spring整合Mybatis、Spring中的事务管理
文章目录 1. 什么是AOP 2. 使用Spring实现AOP 2.1 使用Spring的API 接口实现 2.2 自定义实现 2.3 使用注解实现 3. 整合MyBatis 3.1 MyBatis- ...
- spring中aop事务
文章目录 事务 为什要用到Spring中AOP事务 事物的特性 ACID 事务并发问题 事务的隔离级别 spring事务管理 事务操作 事务操作对象 spring管理事务的属性介绍 spring管理事 ...
- Spring中解决事务以及异步注解失效
Spring中解决事务以及异步注解失效 一.重现@Transaction失效的场景 有如下业务场景,新增订单后,自动发送短信,下面的代码在同一个类中: @Transaction public void ...
- Spring中的事务回滚 网上比较不错的文章
1 浅谈Spring中的事务回滚 https://www.cnblogs.com/zeng1994/p/8257763.html 2 spring 事务回滚 https://www.cnblogs.c ...
- spring事务管理器的作用_【面试必问】Spring中的事务管理详解
在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...
最新文章
- AsyncQueryHandler了解
- 《SAS编程与数据挖掘商业案例》学习笔记之十八
- 一步步编写操作系统80 扩展内联汇编1
- 排序算法之--桶排序(桶,像桶一样的排序,听起来很有趣哦0。0)
- Magento教程 16:Magento价格规则的优先度
- (79)Vivado创建约束的方法
- Python判断某一天是该年的第几天
- innovus停止当前命令_从命令行停止node.js程序
- Clojure 学习入门(7)- 连接mysql
- 路由器刷机教程图解_路由器变砖怎么办救活成功修复TFTP详细图文教程
- 32位win10服务器系统,32位win10原版
- matlab绘制散点密度,MATLAB实例:散点密度图
- 华为最美小姐姐,被外派墨西哥后...
- 市场对计算机专业的需求是怎么样的,计算机专业的行业需求分析
- 利用计算机为祖国做贡献的人,李晓维:祖国,我把科研事业献给您
- 视频提取音频 - 手机视频在线提取音频提取器
- 微信PC端技术研究(2)-保存聊天语音
- Numpy库的安装与初次使用
- 嵌入式开发常用到的在线工具
- python thinker_Thinker