TransactionTemplate编程式事务
目录
一、TransactionTemplate相关源码
Spring支持编程式事务和声明式事务; 因为业务1.需要细粒度更高的事务控制;2.需要频繁与其他系统交互 举例:需要从A系统获取数据,根据获取的数据去跟B系统交互。整理处理完之后再与C系统交互。获取回执返回给A系统。与其他系统的交互掺杂在自己的业务代码中,如果用声明式事务对整个方法进行管控容易出现事务失效或者因系统通讯问题导致事务控制时间过长。所以工作中使用的是编程式事务(统一了事务种类,没有使用声明式事务)。图中绿框范围内的内容涉及到本地数据修改,需要用事务控制(绿框外的部分以数据传递为主,着重记录流水,这部分不纳入事务控制范围),也是业务重点,实际是以多线程方式与B系统交互,出现异常时用事务进行数据回滚和异常日志记录,并且不再执行后续的任务。 框架使用的是spring4.3.4.release版本。
一、TransactionTemplate相关源码
public class TransactionTemplate extends DefaultTransactionDefinitionimplements TransactionOperations, InitializingBean {// 定义事务控制器private PlatformTransactionManager transactionManager;
1)TransactionTemplate类
有三个主要方法:
1> afterPropertiesSet bean实例化->生成对象->属性填充后进行了非空校验
2> execute 任务执行
3> rollbackOnException 回滚方法
一个成员变量:
transactionManager,对应PlatformTransactionManager事务控制器
——execute和rollbackOnException方法里的具体事务控制都是调用的PlatformTransactionManager里的接口方法(具体的事务管理受数据源影响)
public interface PlatformTransactionManager {//根据事务定义TransactionDefinition,获取事务TransactionStatus getTransaction(TransactionDefinition definition);//提交事务void commit(TransactionStatus status);//回滚事务void rollback(TransactionStatus status);
}
补充:由于扩展DefaultTransactionDefinition方法(DefaultTransactionDefinition实现了TransactionDefinition接口),因此TransactionTemplate可以设置事务传播属性、隔离级别信息。
a) 核心方法execute(TransactionCallback<T> action) ,(实现TransactionOperations接口)。
public <T> T execute(TransactionCallback<T> action) throws TransactionException {if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this, action);} else {TransactionStatus status = this.transactionManager.getTransaction(this);Object result;try {result = action.doInTransaction(status);} catch (RuntimeException var5) {this.rollbackOnException(status, var5);throw var5;} catch (Error var6) {this.rollbackOnException(status, var6);throw var6;} catch (Throwable var7) {this.rollbackOnException(status, var7);throw new UndeclaredThrowableException(var7, "TransactionCallback threw undeclared checked exception");}this.transactionManager.commit(status);return result;}}
使用前需要private TransactionTemplate trsTemplate;注入TransactionTemplate事务模板
进而实现TransactionCallback<T>接口的T doInTransaction(TransactionStatus status);方法,通过匿名内部类的方式在doInTransaction里重写需要进行事务控制的业务代码即可。
补充:其实借助TransactionTemplate .
execute(...)执行事务管理的时候,传入的参数有两种选择:
1.TransactionCallback
2.TransactionCallbackWithoutResult
前者有返回值,后者无返回值。两者一般是功能上对读写进行区分。当时项目统一了使用TransactionCallback。
this.trsTemplate.execute(new TransactionCallback() {@Overridepublic Object doInTransaction(TransactionStatus status) {// 需要事务控制的业务代码}return null;}});
b) 事务异常回滚方法:
程序未出现异常时由this.transactionManager.commit(status);进行事务提交,出现异常并能够被程序捕获且处理时由this.rollbackOnException(status, var);进行回滚
private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {this.logger.debug("Initiating transaction rollback on application exception", ex);try {this.transactionManager.rollback(status);} catch (TransactionSystemException var4) {this.logger.error("Application exception overridden by rollback exception", ex);var4.initApplicationException(ex);throw var4;} catch (RuntimeException var5) {this.logger.error("Application exception overridden by rollback exception", ex);throw var5;} catch (Error var6) {this.logger.error("Application exception overridden by rollback error", ex);throw var6;}}
二、事务
补充:Spring事务控制主要有下面三个部分
1.PlatformTransactionManager 事务控制器,spring事务管理的顶层接口(也是TransactionTemplate里使用的)
2.TransactionDefinition 事务基础信息 超时时间、隔离级别、传播属性等
3.TransactionStatus 事务运行状态信息 是否是新事务、是否已被标记为回滚等
1)PlatformTransactionManager事务控制器接口
public interface PlatformTransactionManager {//根据事务定义TransactionDefinition,获取事务TransactionStatus getTransaction(TransactionDefinition definition);//提交事务void commit(TransactionStatus status);//回滚事务void rollback(TransactionStatus status);
}
PlatformTransactionManager接口由AbstractPlatformTransactionManager抽象类实现,因为项目用的是mybatis和ibatis,所以实际使用的是对应子类DataSourceTransactionManage,相关代码挺多的,大致意思是如果没有传入事务定义就用默认定义DefaultTransactionDefinition;如果存在事务,那么进行事务传播属性处理,如果不存在事务就创建新事务并启用。
2)TransactionDefinition事务基础信息接口
之前1)中说的默认事务属性定义方法是DefaultTransactionDefinition实现的
public DefaultTransactionDefinition(TransactionDefinition other) {this.propagationBehavior = other.getPropagationBehavior();this.isolationLevel = other.getIsolationLevel();this.timeout = other.getTimeout();this.readOnly = other.isReadOnly();this.name = other.getName();}// 事务的传播属性 如果没有当前事务就新建,如果有就使用当前事务private int propagationBehavior = PROPAGATION_REQUIRED;// 事务的隔离级别 数据库默认的隔离级别private int isolationLevel = ISOLATION_DEFAULT;// 超时时间采用底层数据库默认的超时时间private int timeout = TIMEOUT_DEFAULT;// 是否只读为falseprivate boolean readOnly = false;private String name;
补充
a).事务的隔离级别是数据库本身的事务功能,然而事务的传播属性则是Spring自己为我们提供的功能,数据库事务没有事务的传播属性这一说法
b).propagationBehavior常见枚举值
看看详解事务的7种传播行为_砖业洋__的博客-CSDN博客_事务的传播行为
c)事务隔离级别待补充,不同数据库不一样,常见是下面几类
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量: T
TransactionDefinition.ISOLATION_DEFAULT:表示使用底层数据库的默认隔离级别。 TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。 TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。 TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。 TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
3.TransactionStatus事务运行状态信息接口
TransactionTemplate类里execute方法获取任务状态就调用AbstractPlatformTransactionManager的对应方法。
TransactionStatus status = this.transactionManager.getTransaction(this);
@Overridepublic final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {Object transaction = doGetTransaction();// Cache debug flag to avoid repeated checks.boolean debugEnabled = logger.isDebugEnabled();if (definition == null) {// Use defaults if no transaction definition given.definition = new DefaultTransactionDefinition();}if (isExistingTransaction(transaction)) {// Existing transaction found -> check propagation behavior to find out how to behave.return handleExistingTransaction(definition, transaction, debugEnabled);}// Check definition settings for new transaction.if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());}// No existing transaction found -> check propagation behavior to find out how to proceed.if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");}else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {SuspendedResourcesHolder suspendedResources = suspend(null);if (debugEnabled) {logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);}try {boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;}catch (RuntimeException ex) {resume(null, suspendedResources);throw ex;}catch (Error err) {resume(null, suspendedResources);throw err;}}else {// Create "empty" transaction: no actual transaction, but potentially synchronization.if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {logger.warn("Custom isolation level specified but no actual transaction initiated; " +"isolation level will effectively be ignored: " + definition);}boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);}}
一般使用DefaultTransactionStatus实现TransactionStatus接口
可以参考全面分析 Spring 的编程式事务管理及声明式事务管理_碧海凌云的博客-CSDN博客
TransactionTemplate编程式事务相关推荐
- 深入理解TransactionTemplate编程式事务
Spring可以支持编程式事务和声明式事务. Spring提供的最原始的事务管理方式是基于TransactionDefinition.PlatformTransactionManager.Transa ...
- 【spring】编程式事务控制
结构: AccountServiceImpl package com.itheima.service.impl;import com.itheima.dao.IAccountDao; import c ...
- 全面分析 Spring 的编程式事务管理及声明式事务管理(转)
摘要 Spring 的事务管理是 Spring 框架中一个比较重要的知识点,该知识点本身并不复杂,只是由于其比较灵活,导致初学者很难把握.本教程从基础知识开始,详细分析了 Spring 事务管理的使用 ...
- 全面分析 Spring 的编程式事务管理及声明式事务管理--转
开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...
- Spring事务处理之 编程式事务 和 声明式事务
对事务概念还不了解的可以先看一下 MySQL事务管理(初步了解) 这篇文章 !!! Spring事务管理学习步骤: 1.掌握Spring事务属性 2.掌握Spring事务核心API 3.掌握Sprin ...
- java编程式事务_Spring编程式和声明式事务实例讲解
Spring事务管理 Spring支持两种方式的事务管理: 编程式事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用, 使用XML配置声明式事务: 推荐使用(代码 ...
- Spring笔记(4) - Spring的编程式事务和声明式事务详解
一.背景 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作 ...
- Spring中两种编程式事务管理
Spring中两种编程式事务管理 在代码中显示调用beginTransaction,commit,rollback等与事务处理相关的方法,这就是编程式事务管理,当只有少数事务操作时,编程式事务管理才比 ...
- 编程式事务和声明式事务浅析
事务管理 在spring中,事物管理一般分为两类,编程式事务管理和声明式事务管理. 编程式事务管理,一般我们使用TransactionTemplate来实现. 声明式事物管理本质上是spring AO ...
最新文章
- SharePoint2010 -- 管理配置文件同步
- 2021年人工神经网络第三次作业-第二题:遗传算法与人工神经网络-参考答案
- java泛型约束_JAVA泛型 - 约束与局限性
- Python 实现斐波那契数列
- NTIRE @ CVPR 2021 视频质量增强竞赛:数据库、方法及结果汇总(官方发布)
- Python统计一个字符串中所有字符在另一个字符串出现的总次数
- Freemarker内置函数使用
- cmd 命令行中乱码问题解决
- 死在路上的创业者们:如何跨越市场推广之坎?
- Installing Perl modules from CPAN
- 常用数字及模拟视频接口
- win无线网卡怎么进入监听模式_win10系统卸载网卡驱动的操作方法
- cad断点快捷键_CAD打断(BREAK)命令的使用技巧
- mysql查询当前用户中所有的表空间_oracle查看用户所在的表空间
- js如何获取滚动条的高度
- 如何修改windows某类后缀文件的图标和系统文件夹的图标
- python openslide 查看并保存切片的略缩图,并将Image图片转换成Base64
- 在app和h5页面中播放视频监控
- 重点人员数据分析管控平台建设,重点人员系统开发
- Python 实现 WSL 2 自动 Windows 主机IP和端口转发,可远程 SSH 登录和访问