2023-09-16  阅读(26)
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105351664

处理回滚流程图

202309162319384251.png

传播机制图

202309162319392602.png

AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理

看上去很像没多少东西,其实里面涉及好多呢,比如如果是新的事务同步状态的话,要把线程的同步状态清除了,如果是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等。如果有挂起的事务,还要把这个事务给恢复,其实就是把属性设置回去。

    private void cleanupAfterCompletion(DefaultTransactionStatus status) {
    		status.setCompleted();
    		if (status.isNewSynchronization()) {
    			TransactionSynchronizationManager.clear();//线程同步状态清除
    		}
    		if (status.isNewTransaction()) {//是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等
    			doCleanupAfterCompletion(status.getTransaction());
    		}
    		if (status.getSuspendedResources() != null) {//有挂起的事务要恢复
    			if (status.isDebug()) {
    				logger.debug("Resuming suspended transaction after completion of inner transaction");
    			}
    			Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
    			resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
    		}
    	}

TransactionSynchronizationManager的clear清除同步状态

就是前面我们设置的线程私有的一些属性。

    	public static void clear() {
    		synchronizations.remove();
    		currentTransactionName.remove();
    		currentTransactionReadOnly.remove();
    		currentTransactionIsolationLevel.remove();
    		actualTransactionActive.remove();
    	}

DataSourceTransactionManager的doCleanupAfterCompletion清除连接相关操作

这里就是做跟连接相关的操作,比如重置自动提交啊,只读属性啊,解绑数据源啊,释放连接啊,清除链接持有器属性啊。

    	@Override
    	protected void doCleanupAfterCompletion(Object transaction) {
    		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    
    		// Remove the connection holder from the thread, if exposed.
    		if (txObject.isNewConnectionHolder()) {//接触数据源和连接的绑定
    			TransactionSynchronizationManager.unbindResource(obtainDataSource());
    		}
    
    		// Reset connection.
    		Connection con = txObject.getConnectionHolder().getConnection();
    		try {
    			if (txObject.isMustRestoreAutoCommit()) {
    				con.setAutoCommit(true);//充实连接自动提交属性
    			}
    			DataSourceUtils.resetConnectionAfterTransaction(//重置隔离级别,是否只读等
    					con, txObject.getPreviousIsolationLevel(), txObject.isReadOnly());
    		}
    		catch (Throwable ex) {
    			logger.debug("Could not reset JDBC Connection after transaction", ex);
    		}
    
    		if (txObject.isNewConnectionHolder()) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
    			}
    			DataSourceUtils.releaseConnection(con, this.dataSource);//释放连接
    		}
    		//连接持有器属性清除
    		txObject.getConnectionHolder().clear();
    	}

TransactionSynchronizationManager的unbindResource解绑数据源

    	public static Object unbindResource(Object key) throws IllegalStateException {
    		//获取数据源
    		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
    		Object value = doUnbindResource(actualKey);//获取解绑的连接持有器
    		if (value == null) {
    			throw new IllegalStateException(
    					"No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
    		}
    		return value;
    	}

其实就是从线程私有变量resources中删除了,这个是个map,因为可能有多个数据源绑定多个连接的。

202309162319397353.png

DataSourceUtils的resetConnectionAfterTransaction重置连接

其实就是重置事务隔离状态和是否只读。

    	public static void resetConnectionAfterTransaction(
    			Connection con, @Nullable Integer previousIsolationLevel, boolean resetReadOnly) {
    		...
    		try {
    			if (previousIsolationLevel != null) {
    				...
    				con.setTransactionIsolation(previousIsolationLevel);
    			}
    			if (resetReadOnly) {
    				...
    				con.setReadOnly(false);
    			}
    		}
    		catch (Throwable ex) {
    			logger.debug("Could not reset JDBC Connection after transaction", ex);
    		}
    	}

DataSourceUtils的releaseConnection释放连接

释放JDBC连接。

    	public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) {
    		try {
    			doReleaseConnection(con, dataSource);
    		}
    		catch (SQLException ex) {
    			logger.debug("Could not close JDBC Connection", ex);
    		}
    		catch (Throwable ex) {
    			logger.debug("Unexpected exception on closing JDBC Connection", ex);
    		}
    	}

doReleaseConnection释放连接

获取连接持有器,释放连接,然后关闭连接。

    	public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException {
    		if (con == null) {
    			return;
    		}
    		if (dataSource != null) {
    			ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);//获取连接持有器,如果前面解除绑定非就拿不到了
    			if (conHolder != null && connectionEquals(conHolder, con)) {//如果连接持有器能拿到的话
    				// It's the transactional Connection: Don't close it.
    				conHolder.released();
    				return;
    			}
    		}
    		doCloseConnection(con, dataSource);//关闭连接
    	}

doCloseConnection关闭连接

如果不是SmartDataSource类型就关闭连接了。

    	public static void doCloseConnection(Connection con, @Nullable DataSource dataSource) throws SQLException {
    		if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
    			con.close();
    		}
    	}

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文