spring事务详解
Spring事务总结
参考
首先,如果整个系统要能实现事务,需要两个方面:
- Spring开启了事务
- MySQL 数据库默认使用支持事务的
innodb
引擎
1.什么是事务?
事务是逻辑上的一组操作,要么都执行,要么都不执行。
2. 事物的特性(ACID)了解么?
- 原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
- 一致性: 执行事务前后,数据保持一致;
- 隔离性: 并发访问数据库时,一个用户的事物不被其他事务所干扰也就是说多个事务并发执行时,一个事务的执行不应影响其他事务的执行;
- 持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
3. 详谈 Spring 对事务的支持
再提醒一次:你的程序是否支持事务首先取决于数据库 ,比如使用 MySQL 的话,如果你选择的是 innodb 引擎,那么恭喜你,是可以支持事务的。但是,如果你的 MySQL 数据库使用的是 myisam 引擎的话,那不好意思,从根上就是不支持事务的。
这里再多提一下一个非常重要的知识点: MySQL 怎么保证原子性的?
- 通过记录**回滚日志(undo log)**进行回滚
- 所有操作记录到回滚日志(undo log)
- 同时**回滚日志(undo log)**可以定时持久化到磁盘上
3.1. Spring 支持两种方式的事务管理
1).编程式事务管理
通过 TransactionTemplate
或者TransactionManager
手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。
try catch的方式,如果如果失败,就在catch中回滚
使用TransactionTemplate
进行编程式事务管理的示例代码如下:
@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {try {// .... 业务代码} catch (Exception e){//回滚transactionStatus.setRollbackOnly();}}});
}
使用 TransactionManager
进行编程式事务管理的示例代码如下:
@Autowired
private PlatformTransactionManager transactionManager;public void testTransaction() {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// .... 业务代码transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}
}
2)声明式事务管理
推荐使用(代码侵入性最小),实际是通过 AOP 实现(基于@Transactional
的全注解方式使用最多)。
使用 @Transactional
注解进行事务管理的示例代码如下:
@Transactional(propagation=propagation.PROPAGATION_REQUIRED)
public void aMethod {//do somethingB b = new B();C c = new C();b.bMethod();c.cMethod();
}
3.2. Spring 事务管理接口介绍
Spring 框架中,事务管理相关最重要的 3 个接口如下:
PlatformTransactionManager
: (平台)事务管理器,Spring 事务策略的核心。 提供了获得,提交,回滚的接口方法。TransactionDefinition
: 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)。TransactionStatus
: 事务运行状态。
我们可以把 PlatformTransactionManager
接口可以被看作是事务上层的管理者,而 TransactionDefinition
和 TransactionStatus
这两个接口可以看作是事物的描述。
PlatformTransactionManager
会根据 TransactionDefinition
的定义比如事务超时时间、隔离界别、传播行为等来进行事务管理 ,而 TransactionStatus
接口则提供了一些方法来获取事务相应的状态比如是否新事务、是否可以回滚等等。
3.2.1. PlatformTransactionManager:事务管理接口
Spring 并不直接管理事务,而是提供了多种事务管理器 。Spring 事务管理器的接口是: PlatformTransactionManager
。
通过这个接口,Spring 为各个平台如 JDBC(DataSourceTransactionManager
)、Hibernate(HibernateTransactionManager
)、JPA(JpaTransactionManager
)等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
PlatformTransactionManager
接口中定义了三个方法:
package org.springframework.transaction;import org.springframework.lang.Nullable;public interface PlatformTransactionManager {//获得事务TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;//提交事务void commit(TransactionStatus var1) throws TransactionException;//回滚事务void rollback(TransactionStatus var1) throws TransactionException;
}
TransactionStatus 接口接口内容如下:
public interface TransactionStatus{boolean isNewTransaction(); // 是否是新的事物boolean hasSavepoint(); // 是否有恢复点void setRollbackOnly(); // 设置为只回滚boolean isRollbackOnly(); // 是否为只回滚boolean isCompleted; // 是否已完成
}
3.2.2. TransactionDefinition:事务属性
事务属性包含了 5 个方面:
隔离级别:(mysql innodb 和 spring 的默认隔离级别都是 可重复读)
根据数据隔离级别
:使用后端数据库默认的隔离级别,MySQL 默认采用的REPEATABLE_READ
隔离级别 Oracle 默认采用的READ_COMMITTED
隔离级别.读未提交
:最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读读已提交
: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生可重复读
: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。序列化
: 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、- 不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
3.3.3. 事务超时属性
所谓事务超时,就是指**一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。**在 TransactionDefinition
中以 int 的值来表示超时时间,其单位是秒,默认值为-1。
3.3.3. 事务只读属性(若类型为readonly,相当于对数据加了读锁)
package org.springframework.transaction;import org.springframework.lang.Nullable;public interface TransactionDefinition {......// 返回是否为只读事务,默认值为 falseboolean isReadOnly();}
对于只有读取数据查询的事务,可以指定事务类型为 readonly,即只读事务。只读事务不涉及数据的修改,数据库会提供一些优化手段,适合用在有多条数据库查询操作的方法中。
3.3.4. 事务回滚规则
这些规则定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常(RuntimeException 的子类)时才会回滚,Error 也会导致事务回滚。
如果你想要回滚你定义的特定的异常类型的话,可以这样:
@Transactional(rollbackFor= MyException.class)
3.4. @Transactional 注解使用详解
1) @Transactional
的作用范围
- 方法 :推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到 public 方法上,否则不生效。
- 类 :如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。
- 接口 :不推荐在接口上使用。
2) @Transactional
的常用配置参数。5个参数,事务传播行为,隔离级别,超时时间,隔离只读属性,回滚的规则
@Transactional
注解源码如下,里面包含了基本事务属性的配置:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {@AliasFor("transactionManager")String value() default "";@AliasFor("value")String transactionManager() default "";Propagation propagation() default Propagation.REQUIRED;Isolation isolation() default Isolation.DEFAULT;int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;boolean readOnly() default false;Class<? extends Throwable>[] rollbackFor() default {};String[] rollbackForClassName() default {};Class<? extends Throwable>[] noRollbackFor() default {};String[] noRollbackForClassName() default {};}
@Transactional
的常用配置参数总结(只列巨额 5 个我平时比较常用的):
属性名 | 说明 |
---|---|
propagation | 事务的传播行为,默认值为 REQUIRED,可选的值在上面介绍过 |
isolation | 事务的隔离级别,默认值采用 DEFAULT,可选的值在上面介绍过 |
timeout | 事务的超时时间,默认值为-1(不会超时)。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
readOnly | 指定事务是否为只读事务,默认值为 false。 |
rollbackFor | 用于指定能够触发事务回滚的异常类型,并且可以指定多个异常类型。 |
3)@Transactional
事务注解原理 - AOP实现
面试中在问 AOP 的时候可能会被问到的一个问题。简单说下吧!
我们知道,@Transactional
的工作机制是基于 AOP 实现的,AOP 又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现了接口,会使用 CGLIB 动态代理。
- 为
@Transactional
注解的类,创建代理类。 - 实际调用的是
TransactionInterceptor
类中的invoke()
方法 - 这个方法的作用就是在目标方法之前开启事务,方法执行过程中如果遇到异常的时候回滚事务,方法调用完成之后提交事务。
4 事务传播行为(方法相互调用时,事务的处理):
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
支持当前事务的情况:
- REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
不支持当前事务的情况:
- REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务放到最后,先执行被调用方法的事务。
- NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务放到最后。简单来说外层有事务,内层不受事务影响。
- NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
嵌套循环事务
- NESTED:如果没有事务,就新建一个事务;如果有,就在当前事务中嵌套其他事务。
NESTED解释:外围方法没有事务:这种情况跟REQUIRED是一样的,会新建一个事务。
外围方法如果存在事务:这种情况就会嵌套事务。所谓嵌套事务,大意就是,外围事务回滚,内嵌事务一定回滚,而内嵌事务可以单独回滚而不影响外围主事务和其他子事务。
spring事务详解相关推荐
- Spring源码(八):Spring事务详解
Spring事务详解 一.事务执行流程 二.Spring事务切面 三.事务切面的Pointcut和Advice 四.注解事务的源码分析 五.Sping事务的传播属性 六.Sping事务的异常校验 七. ...
- Spring事务详解与使用
Spring事务核心对象 J2EE开发使用分层设计的思想进行,对于简单的业务层转调数据层的单一操作,事务开启在业务层或者数据层并无太大差别,当业务中包含多个数据层的调用时,需要在业务层开启事务,对数据 ...
- Spring高级之Spring事务详解(用法、传播行为、隔离级别、只读事务、事务条件)
前言 这是之前开始学spring的时候的笔记,现在添加了一些理解,然后把他搬到博客上来. 事务概述: 这里仅对数据库事务进行一个概述,要详细的可以查询相关文章 在JavaEE企业级开发的应用领域,为确 ...
- Spring 体系结构详解
Spring 体系结构详解 核心容器(Core Container) Core和Beans模块提供了Spring最基础的功能,提供IOC和依赖注入特性.这里的基础概念是BeanFactory,它提供对 ...
- struts2+hibernate+spring配置详解
#struts2+hibernate+spring配置详解 struts2+hibernate+spring配置详解 哎 ,当初一个人做好难,现在终于弄好了,希望自学这个的能少走些弯路. 以下是自己配 ...
- SpringBoot事务详解
文章目录 一.简介 1.介绍 2.事务特点 3.事务实现方式 3.1 MySql事务实现方式 3.2 SpringBoot实现机制 二.@Transactional详解 1.@Transactiona ...
- java JDBC事务和JTA事务详解
什么是事务? 事务其实就是一套数据库操作集合,说到事务就不得不说它的四大特性(A C I D):原子性,一致性,隔离性,持久性.事务的原子性表示事务要么被全部执行,要么被全部不执行.如果事务下的子事务 ...
- Spring入门详解
typora-copy-images-to: upload Spring入门详解 Spring框架是Java开发中最常用的框架,功能非常强大 源码下载:Spring Framework jar包.文档 ...
- 什么是ZooKeeper?可以做什么?ZooKeeper分布式事务详解篇
前言 什么是ZooKeeper,你真的了解它吗.我们一起来看看吧~ 一.什么是 ZooKeeper? ZooKeeper 是 Apache 的一个顶级项目,为分布式应用提供高效.高可用的分布式协调服务 ...
最新文章
- (0030) iOS 开发之跳转之转场动画
- 使用机器学习检测TLS 恶意加密流——业界调研***有开源的数据集,包括恶意证书的,以及恶意tls pcap报文***...
- RSGAN:对抗模型中的“图灵测试”思想
- c++读取utf8文件_经常在日常工作中处理统一码文件(or其他编码)?这篇必读
- 数字信号处理基础知识00
- MySQL存储过程语句(if,while)的使用
- 免费生成十字绣字体_十字绣鞋垫图案 手工鞋垫历史长
- redis3.2版本protected-mode参数
- xp 无法关闭计算机,电脑xp系统关不了机怎么解决
- linux镜像下载与安装
- 手机变身电脑摄像头 Droidcam使用
- 通俗易懂的图解机器学习之机器学习概论
- sax解析xml详解
- 免费云服务器获取方法 云服务器购买
- 就业季必看的职业规划
- 南京标志设计-logo商标设计-企业VI形象识别系统
- 江苏发展大会上有哪些科技界大佬,他们的“隐私”你知道多少?
- 如何查看计算机所连接的打印机
- 股权转让项目:厦门古龙温泉山庄开发有限公司60%股权转让
- 什么是横向扩展、纵向扩展?