目录

  • 一、Spring事务分类
  • 二、Spring事务的三大接口
    • 2.1 PlatformTransationManager接口
    • 2.2 TransactionDefinition接口
    • 2.3 TransactionStatus接口
  • 三、Spring事务嵌套最佳实践
    • 3.1 最佳实践场景一:
    • 3.2 最佳实践场景二:
    • 3.3 最佳实践场景三:
    • 3.4 最佳实践场景四:
    • 3.5 最佳实践场景五:
    • 3.6 最佳实践场景六:
    • 3.7最佳实践场景七:
  • 四、Spring事务失效的场景

一、Spring事务分类

  1. 编程式事务: 如果系统需要明确的事务,并且需要细粒度的控制各个事务的边界,此时建议使用编程式事务
  2. 声明式事务: 如果系统对于事务的控制粒度较为粗糙,则建议使用声明式事务,可以通过注解@Transational实现,原理是利用Spring框架通过AOP代理自动完成开启事务,提交事务,回滚事务。回滚的异常默认是运行时异常,可以通过rollbackFor属性制定回滚的异常类型。

二、Spring事务的三大接口

提示:通过Spring事务的源码可知,Spring不是直接管理事务的,而是提供了多种事务管理器,通过这些事务管理器,Spring将事务委托给了Hibernate、MyBaits、JTA等持久性框架的事务来实现

2.1 PlatformTransationManager接口
public interface PlatformTransactionManager extends TransactionManager {/***  获取事务状态*/TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;/***  提交事务*/void commit(TransactionStatus var1) throws TransactionException;/***  回滚事务*/void rollback(TransactionStatus var1) throws TransactionException;
}
2.2 TransactionDefinition接口
public interface TransactionDefinition {/***  支持当前事务,若当前没有事务就创建一个新的事务*/int PROPAGATION_REQUIRED = 0;/***  如果当前存在事务,则加入该事务,如果当前没有事务,则以非事务的方式继续运行*/int PROPAGATION_SUPPORTS = 1;/***  (强制性的)*  如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常*/int PROPAGATION_MANDATORY = 2;/***  创建一个新的事务,如果当前存在事务,则把当前事务挂起*/int PROPAGATION_REQUIRES_NEW = 3;/*** 以非事务方式运行,如果当前存在事务,则把当前事务挂起*/int PROPAGATION_NOT_SUPPORTED = 4;/*** 以非事务的方式运行,如果当前存在事务,则抛出异常*/int PROPAGATION_NEVER = 5;/*** (嵌套的)* 表示如果当前正有一个事务在运行中,则该方法运行在一个嵌套的事务中,被嵌套的事务可以独立于封装的事务进行提交或者回滚(这里需要事务的保存点),如果封装的事务不存在,后续事务行为同PROPAGATION_REQUIRES_NEW*/int PROPAGATION_NESTED = 6;/***  使用后端的默认隔离级别*/int ISOLATION_DEFAULT = -1;/*** 读未提交*/int ISOLATION_READ_UNCOMMITTED = 1;/** * 读已提交*/int ISOLATION_READ_COMMITTED = 2;/*** 可重复度*/int ISOLATION_REPEATABLE_READ = 4;/** * 串行化*/int ISOLATION_SERIALIZABLE = 8;int TIMEOUT_DEFAULT = -1;default int getPropagationBehavior() {return 0;}default int getIsolationLevel() {return -1;}default int getTimeout() {return -1;}default boolean isReadOnly() {return false;}@Nullabledefault String getName() {return null;}static TransactionDefinition withDefaults() {return StaticTransactionDefinition.INSTANCE;}
}
2.3 TransactionStatus接口
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {/***  是否有保存点*/boolean hasSavepoint();/***  将事务涉及的数据刷新到磁盘*/void flush();
}

三、Spring事务嵌套最佳实践

我们将此方法作为内部方法,有外部方法调用此方法,我们在方法的最后面故意制造了算术异常来检验以下场景:

 /*** 项目延期** @param id    工单id* @param value 延期天数* @return*/@Override@Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)public Boolean projectDelay(String id, Integer value) {EqOverhaulWorkOrderEntity eqOverhaulWorkOrderEntity = eqOverhaulWorkOrderMapper.selectById(id);Date startTime = eqOverhaulWorkOrderEntity.getStartTime();Calendar calendar = Calendar.getInstance();calendar.setTime(startTime);calendar.add(Calendar.DAY_OF_MONTH, value);eqOverhaulWorkOrderEntity.setStartTime(calendar.getTime());int update = eqOverhaulWorkOrderMapper.updateById(eqOverhaulWorkOrderEntity);int i = 1/0;return update == 1;}
3.1 最佳实践场景一:

场景一为外部方法无事务注解,内部方法添加REQUIRED事务传播类型:
总结: 内部方法抛出异常,内部方法执行失败,不会影响外部方法的执行,外部方法执行成功。

3.2 最佳实践场景二:

场景二为外部方法添加REQUIRED事务传播类型,内部方法无事务注解。
总结: 内部方法抛出异常,会影响外部方法的执行,导致外部事务的回滚。

3.3 最佳实践场景三:

场景三为外部方法添加REQUIRED事务传播类型,内部方法添加REQUIRED事务传播类型。
总结: 内部方法抛出异常,会影响外部方法的执行,事务回滚。

3.4 最佳实践场景四:

场景四为外部方法添加REQUIRED事务传播类型,内部方法添加NOT_SUPPORTED事务传播类型。
总结: 内部方法抛出异常,外部方法回滚,内部方法不会回滚,外部方法抛出异常,内部方法执行成功,内部方法提交,内部方法抛出异常,也不会回滚。内部方法永远不会回滚。

3.5 最佳实践场景五:

场景五外部方法添加REQUIRED事务传播类型,内部方法添加REQUIRED_NEW事务传播类型。
总结:内部方法抛出异常,内部方法和外部方法都会执行失败,事务回滚。

3.6 最佳实践场景六:

场景六为外部方法添加REQUIRED事务传播类型,内部方法添加REQUIRED_NEW事务传播类型,并且把异常代码移动到外部方法的尾部。
总结: 外部方法抛出异常,外部方法执行失败,事务回滚,内部方法执行成功,内部方法事务提交。

3.7最佳实践场景七:

场景七为外部方法添加REQUIRED,内部方法添加REQUIRED_NEW事务传播类型,并且把异常代码移动到外部方法的尾部,同时外部方法和内部方法在同一个类中。
总结: 外部方法抛出异常, 内部方法和外部方法都会回滚。

四、Spring事务失效的场景

  1. 数据库不支持事务
  2. 事务方法未被Spring管理,也就是事务方法所在的类没有加载到Spring IOC容器中
  3. 方法没有被public修饰
    @Override@Transactional(rollbackFor = Exception.class)private Boolean projectDelay(String id, Integer value) {EqOverhaulWorkOrderEntity eqOverhaulWorkOrderEntity = eqOverhaulWorkOrderMapper.selectById(id);Date startTime = eqOverhaulWorkOrderEntity.getStartTime();Calendar calendar = Calendar.getInstance();calendar.setTime(startTime);calendar.add(Calendar.DAY_OF_MONTH, value);eqOverhaulWorkOrderEntity.setStartTime(calendar.getTime());int update = eqOverhaulWorkOrderMapper.updateById(eqOverhaulWorkOrderEntity);return update == 1;}

因为方法是私有的,加在私有方法上的事务注解不生效。
4. 在同一个类中的方法调用。
提示:举例详情见最佳实践场景七
5. 方法的事务传播类型不支持事务。
提示:举例详情见最佳实践场景四
6. 不正确地捕获异常。
使用了try-catch代码块将异常捕捉了,没有向上抛出异常,事务不会回滚。
7.标注错误的异常类型。
Spring事务默认回滚类型是RuntimeException类型,如果没有制定回滚的类型,抛出的错误不是RuntimeException类型,则无法回滚

Spring事务的实现原理相关推荐

  1. 《深入理解分布式事务》第三章 Spring 事务的实现原理

    <深入理解分布式事务>第三章 Spring 事务的实现原理 文章目录 <深入理解分布式事务>第三章 Spring 事务的实现原理 一.Spring 事务原理 1.JDBC 直接 ...

  2. jdbctemplate 开启事务_浅入浅出 Spring 事务传播实现原理

    本文和大家一起刨析 Spring 事务的相关源码,篇幅较长,代码片段较多,建议使用电脑阅读 本文目标 理解Spring事务管理核心接口 理解Spring事务管理的核心逻辑 理解事务的传播类型及其实现原 ...

  3. Spring事务传播实现原理

    什么是事务传播? 假设这样一个场景:方法A上面添加了一个@Transactional注解,在该方法中去调用另一个Service的方法B,但方法B并不需要事务,但是由于A开启了事务,导致B方法的执行也处 ...

  4. Spring 事务用法示例与实现原理

    关于事务,简单来说,就是为了保证数据完整性而存在的一种工具,其主要有四大特性:原子性,一致性,隔离性和持久性.对于Spring事务,其最终还是在数据库层面实现的,而Spring只是以一种比较优雅的方式 ...

  5. Spring事务原理一探

    概括来讲,事务是一个由有限操作集合组成的逻辑单元.事务操作包含两个目的,数据一致以及操作隔离.数据一致是指事务提交时保证事务内的所有操作都成功完成,并且更改永久生效:事务回滚时,保证能够恢复到事务执行 ...

  6. 【技术干货】Spring事务原理一探

    本篇文章是网易云信研发工程师对Spring事务实现原理及实现的研究和总结,分享给大家,希望和大家共同探讨. 事务是一个由有限操作集合组成的逻辑单元.事务操作包含两个目的,数据一致以及操作隔离.数据一致 ...

  7. Spring事务实现的方式及底层原理

    spring事务的实现方式 spring框架提供了两种事务实现方式:编程式事务.声明式事务 编程式事务:在代码中进行事务控制.优点:精度高.缺点:代码耦合度高 声明式事务:通过@Transaction ...

  8. Spring 事务原理篇:@EnableTransactionManagement注解底层原理分析技巧,就算你看不懂源码,也要学会这个技巧!

    前言 学习了关于Spring AOP原理以及事务的基础知识后,今天咱们来聊聊Spring在底层是如何操作事务的.如果阅读到此文章,并且对Spring AOP原理不太了解的话,建议先阅读下本人的这篇文章 ...

  9. Spring事务原理-1-transactionManager以及Connection的本质

    Spring事务原理 1.spring事务配置 2.Connection本质的探究 3. Spring事务的底层原理 1.spring事务配置 <bean id="transactio ...

最新文章

  1. 进程管理supervisor的简单说明
  2. live联系人导出到CSV乱码
  3. 反病毒引擎设计全解(二)
  4. oracle 11g 清除 trc后缀文件,请教一个跟踪文件的问题。11g 很多trc文件。。
  5. 2016年《大数据》高被引论文Top10
  6. 使用火狐的restclient发送http接口post及get请求
  7. Python 关键词触发的魔法方法
  8. python美化输出模块_美化输出结果之Python模块PrettyTable介绍
  9. LevelDB的源码阅读(三) Get操作
  10. 使用ViewPager + Fragment实现微信底部Tab效果
  11. 泄露你的JavaScript技术很烂的五个表现
  12. 弱键(Weak Key, ACM/ICPC Seoul 2004, UVa1618)
  13. 模拟电子技术动画-PN结(动画是转的)内容再修改
  14. 如何在SendWS做到WhatsApp客服系统,WhatsApp云控客服系统有作用?为什么选择WhatsApp做海外营销推广?
  15. 本地文件上传到github
  16. excel中插入的图表保存时提示 无法保存 html,excel表格保存不了的解决方法步骤...
  17. FastJson的JSON.isValid()出现BUG!
  18. 【Proteus仿真】Arduino UNO+OLED12864 I2C接口跑图形库
  19. seo主导下的内容建设
  20. SpringCloud系列之六

热门文章

  1. 浅谈IM软件如何建立安全socket连接、登录
  2. 程序员当年的烂代码被人挖出来后……
  3. Ubuntu 16.04 安装手札
  4. Shodan:最令人恐惧的搜索引擎
  5. 记录:jenkins打包项目,代码不生效
  6. 日常自写的小脚本 一
  7. selenium验证码登录_如何用 Python 登录主流网站,爬取一些需要的数据
  8. jQuery - 点击图片加边框
  9. 如何查询自家的网络有没有被DNS劫持?dns劫持是什么
  10. Scala学习(二)groupByKey和reduceByKey