写在前面

  TransactionStatus表示一个具体的事务状态(这里应用到了Java的一个多继承,接口允许多继承

  TransactionStatus它继承了SavepointManager接口,SavepointManager是对事务中上述保存点功能的封装(Spring利用保存点功能实现了事务的嵌套功能。后面会详细说明)

public interface SavepointManager {
Object createSavepoint() throws TransactionException;
void rollbackToSavepoint(Object savepoint) throws TransactionException;
void releaseSavepoint(Object savepoint) throws TransactionException;
}
public interface TransactionStatus extends SavepointManager, Flushable {
//是否是一个新的事物
boolean isNewTransaction();
//是否有保存点
boolean hasSavepoint();
void setRollbackOnly();
//是否已被标记为回滚
boolean isRollbackOnly();
@Override
void flush();
boolean isCompleted();
}

DefaultTransactionStatus

常用的TransactionStatus接口实现为DefaultTransactionStatus:

public class DefaultTransactionStatus extends AbstractTransactionStatus {

    private final Object transaction;

    private final boolean newTransaction;

    private final boolean newSynchronization;

    private final boolean readOnly;

    private final boolean debug;

    private final Object suspendedResources;
}

  目前jdbc事务是通过Connection来实现事务的,Hibernate是通过它自己定义的Transaction来实现的,所以各家的事务都不同,所以Spring只能以Object transaction的形式来表示各家的事务,事务的回滚和提交等操作都会最终委托给上述Object transaction来完成。

  Object transaction的职责就是提交回滚事务,这个transaction的选择可能如下:

    • DataSourceTransactionObject
    • HibernateTransactionObject
    • JpaTransactionObject

  详细信息分别如下:

  • DataSourceTransactionObject:

    我们使用了dataSource来获取连接,要想实现事务功能,必然需要使用Connection,所以它中肯定有一个Connection来执行事务的操作。DataSourceTransactionObject中有一个ConnectionHolder,它封装了一个Connection。

  • HibernateTransactionObject:

    我们使用了hibenrate,此时要想实现事务功能,必然需要通过hibernate自己定义的Transaction来实现。

HibernateTransactionObject中含有一个SessionHolder,和上面的ConnectionHolder一样,它封装了一个Session,有了Session,我们就可以通过Session来产生一个Hibernate的Transaction,从而实现事务操作。

DefaultTransactionStatus的获取

  DefaultTransactionStatus的获取是事务管理器的方法,这里的实现是AbstractPlatformTransactionManager提供的模板方法

  在获取Object transaction之后,先进行判断,是否是已存在的事务。因为这个Object transaction的获取过程就是直接从线程绑定的获取的,可能当前线程已经存在事务

    @Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
     //获取相应的Object transaction
Object transaction = doGetTransaction();
     //就是依据和当前线程绑定的ConnectionHolder中是否已存在事务(也是依据和当前线程绑定的SessionHolder是否已存在事务)
if (isExistingTransaction(transaction)) {
       //如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法:
return handleExistingTransaction(definition, transaction, debugEnabled);
}
     ...
}

 

  如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法

    private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
     // PROPAGATION_NEVER:不允许存在事务,如果存在抛出异常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
     // PROPAGATION_NOT_SUPPORTED:不支持事务,如果存在事务,则需将事务挂起,保存起来,当执行完成之后,需要将挂起的事务继续恢复
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
     //PROPAGATION_REQUIRES_NEW:开启一个新的事务,如果当前存在事务则把当前事务挂起来
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
         //可以看到,创建新的事务,就会调用doBegin(transaction, definition);方法,将事务开启。
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
catch (Error beginErr) {
resumeAfterBeginException(transaction, suspendedResources, beginErr);
throw beginErr;
}
} if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
} // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
     //PROPAGATION_SUPPORTS 和 PROPAGATION_REQUIRED 如果当前存在事务,则仍旧使用该事物  
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

  

  事务的挂起

  对于DataSourceTransactionManager来说,事务的挂起,就是把当前线程关联的ConnectionHolder解除绑定、同理事务的恢复就是把上述ConnectionHolder再重新绑定到当前线程,继续执行该事务

    @Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
//解除绑定dataSource, conHolder 至 TransactionSynchronizationManager
ConnectionHolder conHolder = (ConnectionHolder)
TransactionSynchronizationManager.unbindResource(this.dataSource);
return conHolder;
} @Override
protected void doResume(Object transaction, Object suspendedResources) {
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
     //重新绑定dataSource, conHolder 至 TransactionSynchronizationManager
TransactionSynchronizationManager.bindResource(this.dataSource, conHolder);
}

spring---transaction(4)---源代码分析(事务的状态TransactionStatus)的更多相关文章

  1. spring transaction源码分析--事务架构

    1. 引言  事务特性 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性.事 ...

  2. spring---transaction(1)---源代码分析(事务的拦截器TransactionInterceptor)

    写在前面: 先了解一下spring的事务.分为分明式事务管理和注解式事务管理,对于前期的事务,spring会通过扫描拦截对于事务的方法进行增强(以后讲解). 若果目标方法存在事务,spring产出的b ...

  3. spring---transaction(3)---源代码分析(事务的管理器PlatformTransactionManager)

    写在前面 由于实现事务功能的方式各不相同,Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器顶级接口(平台事务管理器),事务的提交.回滚等操作全部交给它 ...

  4. spring---transaction(2)---源代码分析(事务的定义TransactionDefinition)

    写在前面 事务属性通过TransactionDefinition接口实现定义,主要有事务隔离级别.事务传播行为.事务超时时间.事务是否只读. public interface TransactionD ...

  5. 看透Spring MVC:源代码分析与实践 (Web开发技术丛书)

    第一篇 网站基础知识 第1章 网站架构及其演变过程2 1.1 软件的三大类型2 1.2 基础的结构并不简单3 1.3 架构演变的起点5 1.4 海量数据的解决方案5 1.4.1 缓存和页面静态化5 1 ...

  6. spring(六):事务

    事务特性ACID 原子性(Atomicity):即事务是不可分割的最小工作单元,事务内的操作要么全做,要么全不做: 一致性(Consistency):在事务执行前数据库的数据处于正确的状态,而事务执行 ...

  7. spring Transaction Propagation 事务传播

    spring Transaction中有一个很重要的属性:Propagation.主要用来配置当前需要执行的方法,与当前是否有transaction之间的关系. 我晓得有点儿抽象,这也是为什么我想要写 ...

  8. 《深入实践Spring Boot》阅读笔记之三:核心技术源代码分析

    刚关注的朋友,可以回顾前两篇文章: 基础应用开发 分布式应用开发 上篇文章总结了<深入实践Spring Boot>的第二部分,本篇文章总结第三部分,也是最后一部分.这部分主要讲解核心技术的 ...

  9. RocketMQ源码分析之RocketMQ事务消息实现原理中篇----事务消息状态回查

    上节已经梳理了RocketMQ发送事务消息的流程(基于二阶段提交),本节将继续深入学习事务状态消息回查,我们知道,第一次提交到消息服务器时消息的主题被替换为RMQ_SYS_TRANS_HALF_TOP ...

随机推荐

  1. React-Native 之 常用组件Image使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  2. mysql高可用架构 -> MHA简介-01

    作者简介 松信嘉範:MySQL/Linux专家2001年索尼公司入职2001年开始使用oracle2004年开始使用MySQL2006年9月-2010年8月MySQL从事顾问2010年-2012年 D ...

  3. POJ 2955 Brackets(括号匹配一)

    题目链接:http://poj.org/problem?id=2955 题目大意:给你一串字符串,求最大的括号匹配数. 解题思路: 设dp[i][j]是[i,j]的最大括号匹配对数. 则得到状态转移方 ...

  4. The Art Of Computer Programming: 1.1

    The Art Of Computer Programming: 1.1 */--> div.org-src-container { font-size: 85%; font-family: m ...

  5. Tensorflow之训练MNIST(1)

    先说我遇到的一个坑,在下载MNIST训练数据的时候,代码报错: urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FA ...

  6. 微商城三级分销源码公众号开发 微分销 C#源码

    需要源码,请加QQ:858-048-581 ,可以查看演示 运行环境:vs2012+ sql2008r2 [什么是微分销] 微分销是助力企业进军移动电商,完善分销体系搭建微信分销系统.基于微信平台,搭 ...

  7. VMware虚拟机Mac OS X无法调整扩展硬盘大小的解决方案

    使用VMware虚拟机搭建的MacOSX,在10.10以上可能会出现无法扩充磁盘大小的问题. 因为很多朋友在初次安装MacOSX的时候都默认选择40G的磁盘大小,结果用了没两天之后就发现磁盘不够用了. ...

  8. Kylin使用笔记-0: kylin介绍

    APACHE KYLIN™ 概览 Apache Kylin™是一个开源的分布式分析引擎,提供Hadoop之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBay Inc. 开发 ...

  9. 【51nod】1773 A国的贸易

    题解 FWT板子题 可以发现 \(dp[i][u] = \sum_{i = 0}^{N - 1} dp[i - 1][u xor (2^i)] + dp[i - 1][u]\) 然后如果把异或提出来可 ...

  10. CROC 2016 - Elimination Round (Rated Unofficial Edition) F - Cowslip Collections 数论 + 容斥

    F - Cowslip Collections http://codeforces.com/blog/entry/43868 这个题解讲的很好... #include<bits/stdc++.h ...