一.说明

@Tranasctional注解是Spring 框架提供的声明式注解事务解决方案,我们在开发中使用事务保证方法对数据库操作的原子性,要么全部成功,要么全部失败,在使用@Transactional注解时需要注意以下问题:

1. @Transactional  注解只能用在public 方法上,如果用在protected或者private的方法上,不会报错,但是该注解不会生效。外部调用才能生效,内部调用不生效。

2. @Transactional注解只能回滚非检查型异常,具体为RuntimeException及其子类和Error子类,可以从Spring源码的DefaultTransactionAttribute类里找到判断方法rollbackOn。

 @Overridepublic boolean rollbackOn(Throwable ex) {return (ex instanceof RuntimeException || ex instanceof Error);}

3. @Transactional 使用rollbackFor 属性来定义回滚的异常类型,使用 propagation 属性定义事务的传播行为。如:   回滚Exception类的异常,事务的传播行为支持当前事务,当前如果没有事务,那么会创建一个事务,默认的propagation是REQUIRED

 @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)

4. @Transactional注解不能回滚被try{}catch() 捕获的异常。

5. @Transactional注解只能对在被Spring 容器扫描到的类下的方法生效。


二.事务的传播行为

事务行为 说明
PROPAGATION_REQUIRED 如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
PROPAGATION_SUPPORTS 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
PROPAGATION_MANDATORY 必须在一个已有的事务中执行,否则抛出异常
PROPAGATION_REQUIRES_NEW 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
PROPAGATION_NOT_SUPPORTED 容器不为这个方法开启事务
PROPAGATION_NEVER 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED 类似的操作。

三.业务场景案例

需求:每一个checker的调用都需要开启事务(doChecking方法),但是EqFundEqInvestmentLimitChecker 的这个checker里面需要用到EqPortAverageDateServiceImpl .prepareEqPortPctData()方法的保存数据

解决:单独提交方法需要放在不用的服务类里,使用@Transactional的propagation属性来实现隔离事务。设置propagation等于Propagation.REQUIRES_NEW,表示开启单独事务,不受其他事务影响。这样就可以让prepareEqPortPctData()作为一个父事务里面单独的子事务,执行完会将数据保存到数据库,这样checker就可以拿到新保存的数据作处理。

@Service
public class EqPortAverageDateServiceImpl implements EqPortAverageDateService{@Override@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)public void prepareEqPortPctData(LimitExceptionContext limitExceptionContext) {this.saveBatch();System.out.println("业务逻辑");}}
}@Component
public class TradeOrderCheckingServiceImpl {@Transactional(rollbackFor = Exception.class)public void dochecking(LimitExceptionContext limitExceptionContext) {EqFundEqInvestmentLimitChecker.checking(limitExceptionContext);}
}@Component
public class EqFundEqInvestmentLimitChecker {public void checking(LimitExceptionContext limitExceptionContext) {eqPortAverageDateService.prepareEqPortPctData(limitExceptionContext);prepareData();setException();}
}

Tips:

PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别:

它们非常类似,都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。 
使用 PROPAGATION_REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务管理器的支持。

使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED时,需要JDBC 3.0以上驱动及1.4以上的JDK版本支持。其它的JTATrasactionManager实现可能有不同的支持方式。

PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 “内部” 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行。

另一方面, PROPAGATION_NESTED 开始一个 “嵌套的” 事务, 它是已经存在事务的一个真正的子事务. 潜套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。

由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 这个规则同样适用于 roll back.


注:本篇文章结合了其他我觉得写的比较好的文章总结而成,如需要去看源码解析的可以自行前往以下地址:@Transactional注解详细使用_Dream_it_possible!的博客-CSDN博客_@transactional注解

Spring 事务Transaction源码深度解析_Dream_it_possible!的博客-CSDN博客_spring事务源码深度解析 感谢

@Transactional 使用说明相关推荐

  1. 常见的 @Transactional 注解,你确定用对了吗?

    @Transactional属性详解 声明式事务管理建立在AOP之上的.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务. 简而 ...

  2. spring同类方法调用事务使用说明

    2019独角兽企业重金招聘Python工程师标准>>> #spring声明式事务使用说明: #前提: 1.springboot 2.0.3.RELEASE 2.application ...

  3. java rollback_Spring中的@Transactional(rollbackFor = Exception.class)属性详解

    序言 今天我在写代码的时候,看到了.一个注解@Transactional(rollbackFor = Exception.class),今天就和大家分享一下,这个注解的用法: 异常 如下图所示,我们都 ...

  4. @Transactional(rollbackFor = Exception.class) 详解

    17.@Transactional(rollbackFor = Exception.class) 详解 1.参考来源:https://www.cnblogs.com/clwydjgs/p/931784 ...

  5. mysqldump 忽略视图_mysqldump 使用说明

    mysqldump 使用说明 A Database Backup Program mysqldump客户端是一款实用的mysql备份程序,可以对数据库的定义及数据表内容,进行备份生成相应的SQL语句. ...

  6. @Transactional注解最容易忽视的三个失效场景!

    @Transactional注解在以下场景中使用,是会失效的,切记! 1.非public方法 spring对注解事务的方法进行校验,修饰符是不是public,不是 public则不会获取@Transa ...

  7. abaqus高性能服务器怎么用,高性能计算平台ABAQUS任务调度使用说明作者陈林E-Mailchenlin.PDF...

    高性能计算平台ABAQUS任务调度使用说明作者陈林E-Mailchenlin.PDF 高性能计算平台ABAQUS 任务调度使用说明 作者:陈林 E-Mail:chenlin@ 日期:2017-1-10 ...

  8. linux 文件拷贝并替换,Linux_cmd replace 文件替换使用说明,帮助信息: 复制代码 代码如 - phpStudy...

    cmd replace 文件替换使用说明 帮助信息: 复制代码 代码如下: 替换文件. REPLACE [drive1:][path1]filename [drive2:][path2] [/A] [ ...

  9. Simple Dynamic Strings(SDS)源码解析和使用说明二

    在<Simple Dynamic Strings(SDS)源码解析和使用说明一>文中,我们分析了SDS库中数据的基本结构和创建.释放等方法.本文将介绍其一些其他方法及实现.(转载请指明出于 ...

最新文章

  1. NASA WorldWind1.4.0源代码调试总结
  2. 冷藏温度范围_食品冷藏冷冻温度要求与管理规范
  3. Java Scanner nextLine()方法与示例
  4. 全球最畅销的10款手机:iPhone 11继续无敌,能对拼的只有它!
  5. 跟我学SpringMVC目录汇总贴、PDF下载、源码下载
  6. java 同步 set_Java Collections synchronizedSet()用法及代码示例
  7. u盘锁电脑_如何给u盘设置密码 给u盘设置密码方法【步骤详解】
  8. 用RDA方式同步SQLCE与SQL SERVER数据库
  9. SCVMM2012 SP1 之添加非受信任Hyper-V
  10. 通信upf是什么意思_中兴通讯全场景UPF 极简设计,随需而动
  11. 接口测试一般怎么测?接口测试的流程和步骤
  12. LTE学习笔记五:LTE两种帧结构
  13. 针对iPhone X和iPhone XS这些傻叉手机安全距离的设定
  14. Win10如何使用win7的照片查看器
  15. 串级PID和 前馈系统
  16. 云计算学习1——OpenStack云计算安装部署步骤图文并茂(先电2.2)
  17. 历史课堂上的经典对白
  18. 台湾国立大学(林轩田)《机器学习技法》(第7讲)blending and bagging
  19. 谷歌云| 5 个 GKE 功能可帮助您优化集群
  20. 影牛社区短视频APP源码/最火短视频类APP源码下载

热门文章

  1. Django使用MySQL数据库
  2. mysql锁表原因及解决
  3. 算法设计与分析基础知识点
  4. Java的字节流和字符流
  5. 俄勒冈大学计算机科学专业,2020年俄勒冈大学排名TFE Times美国最佳计算机科学硕士专业排名第68...
  6. gcov的实现原理简介
  7. 原材料行业经销商在线管理系统:提升经销商管理品质,优化分销渠道
  8. 数据分析01 - 规范化方法
  9. Java基础及API总结
  10. 兔将十年大作《赤狐书生》特效解析:青蛙精篇