广告
返回顶部
首页 > 资讯 > 后端开发 > Python >spring的事务传播属性REQUIRED_NESTED原理
  • 783
分享到

spring的事务传播属性REQUIRED_NESTED原理

spring事务传播事务传播属性REQUIRED_NESTED原理 2023-05-20 08:05:04 783人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录传统事务中回滚点的使用事务的传播属性NESTEDaddAreaAndGood()开启事务addGood()获得事务并创建回滚点addGood()提交事务时释放回滚点addArea

传统事务中回滚点的使用

package com.morris.spring.demo.jdbc;
import java.sql.*;

public class TraditionSavePointDemo {
	public static void main(String[] args) throws SQLException {
		String url = "jdbc:Mysql://127.0.0.1:3306/test?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8&useFastDateParsing=false&zeroDateTimeBehavior=convertToNull";
		String username = "user";
		String passWord = "user";
		Connection connection = DriverManager.getConnection(url, username, password);
		connection.setAutoCommit(false); // 不自动提交
		Savepoint one = connection.setSavepoint("one");
		Savepoint two = null;
		try {
			Statement statement = connection.createStatement();
			statement.execute("insert into t_good(good_name, price) values('iphone14', 9999)");
			statement.close();
			two = connection.setSavepoint("two");
		} catch (Exception e) {
			e.printStackTrace();
			connection.rollback(one); // 回滚事务
		}
		try {
			Statement statement = connection.createStatement();
			statement.execute("insert into t_good(good_name, price) values('iphone15', 9999)");
			statement.close();
			boolean flag = true;
			if(flag) {
				throw new RuntimeException("xxxx");
			}
		} catch (Exception e) {
			e.printStackTrace();
			connection.rollback(two); // 回滚事务
		}
		connection.commit();
	}
}

在一个事务中可以指定回滚事务到某一个阶段,实现精确控制事务。

事务的传播属性NESTED

在spring中,要想使用事务中的回滚点,可以使用传播属性NESTED。

com.morris.spring.service.TransactionService#addGoodAndArea

@Transactional(propagation = Propagation.REQUIRED)
public void addGoodAndArea() {
	System.out.println("------addGoodAndArea-------");
	goodService.addGood();
	areaService.addArea(0);
}

com.morris.spring.service.AreaServiceImpl#addArea

@Transactional(propagation = Propagation.NESTED)
@Override
public boolean addArea(int i) {
	int y = 1000000 / i;
	Area area = new Area();
	area.setAreaCode(y);
	area.setAreaName("shenzhen");
	return areaDao.insert(area);
}

com.morris.spring.service.GoodServiceImpl#addGood

@Transactional(propagation = Propagation.NESTED)
@Override
public boolean addGood() {
	Good good = new Good();
	good.setGoodName("iphone");
	good.setPrice(BigDecimal.valueOf(99999));
	return goodDao.insert(good);
}

运行结果如下:

DEBUG DataSourceTransactionManager:384 - Creating new transaction with name [com.morris.spring.service.TransactionService.addGoodAndArea]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG DriverManagerDataSource:144 - Creating new JDBC DriverManager Connection to [jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8&useFastDateParsing=false&zeroDateTimeBehavior=convertToNull]
DEBUG DataSourceTransactionManager:267 - Acquired Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162] for JDBC transaction
DEBUG DataSourceTransactionManager:285 - Switching JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162] to manual commit
------addGoodAndArea-------
DEBUG DataSourceTransactionManager:477 - Creating nested transaction with name [com.morris.spring.service.GoodServiceImpl.addGood]
DEBUG JdbcTemplate:860 - Executing prepared SQL update
DEBUG JdbcTemplate:609 - Executing prepared SQL statement [insert into t_good(good_name, price) values(?,?)]
DEBUG DataSourceTransactionManager:767 - Releasing transaction savepoint
DEBUG DataSourceTransactionManager:477 - Creating nested transaction with name [com.morris.spring.service.AreaServiceImpl.addArea]
DEBUG DataSourceTransactionManager:870 - Rolling back transaction to savepoint
DEBUG DataSourceTransactionManager:877 - Initiating transaction rollback
DEBUG DataSourceTransactionManager:347 - Rolling back JDBC transaction on Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162]
DEBUG DataSourceTransactionManager:392 - Releasing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@8ef162] after transaction
java.lang.ArithmeticException: / by zero
... ...

发现整个事务都已经回滚了,按照回滚点的逻辑,addArea()方法抛出异常,不是应该只回滚到addArea()前吗,也就是addGood()应该被提交,这是为什么呢?

如果我们将addArea()方法try catch起来,就能得到我们想要的结果,addGood()被提交,而addArea()回滚,这又是为什么呢?我们带着这几个问题来分析源码

addAreaAndGood()开启事务

addAreaAndGood()开启事务,最外层方法使用传播属性PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED效果都一样,都是开启一个新的事务。

org.springframework.transaction.support.AbstractPlatfORMTransactionManager#getTransaction

else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
		def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
		def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	// 第一次进来
	SuspendedResourcesHolder suspendedResources = suspend(null);
	if (debugEnabled) {
		logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
	}
	try {
		// 开启新事务
		return startTransaction(def, transaction, debugEnabled, suspendedResources);
	}
	catch (RuntimeException | Error ex) {
		resume(null, suspendedResources);
		throw ex;
	}
}

addGood()获得事务并创建回滚点

addGood()从ThreadLocal中获得addAreaAndGood()创建的事务,然后发现自己的传播属性为PROPAGATION_NESTED,就创建了一个回滚点。

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

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.
		return startTransaction(definition, transaction, debugEnabled, null);
	}
}

addGood()提交事务时释放回滚点

addGood()并不会真正的提交事务,因为事务并不是addGood()创建的,只是在提交时会将之前创建的回滚点释放。

org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit

if (status.hasSavepoint()) {
	// NESTED的提交
	if (status.isDebug()) {
		logger.debug("Releasing transaction savepoint");
	}
	unexpectedRollback = status.isGlobalRollbackOnly();
	// 只是释放回滚点
	status.releaseHeldSavepoint();
}

addArea()获得事务并创建回滚点

流程与addGood()一致。

addArea()回滚事务释放回滚点

addArea()发生异常,会执行回滚事务的逻辑,并没有真正的回滚事务,因为事务并不是addArea()创建的,,只是将之前创建的回滚点释放。 org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

if (status.hasSavepoint()) {
	// 用于NESTED传播机制,发生异常
	// 回滚至回滚点
	if (status.isDebug()) {
		logger.debug("Rolling back transaction to savepoint");
	}
	status.rollbackToHeldSavepoint();
}

addAreaAndGood()回滚这个事务

addArea()发生异常后继续往外抛,addAreaAndGood()也会捕获到异常,然后执行回滚逻辑,这样整个事务都回滚了。 org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

else if (status.isNewTransaction()) {
	// 只有最外层的事务newTransaction=true
	if (status.isDebug()) {
		logger.debug("Initiating transaction rollback");
	}
	// 事务的回滚
	
	doRollback(status);
}

为什么将addArea()方法try catch起来,整个事务就不会回滚了呢?

因为将addArea()方法try catch起来后,addAreaAndGood()就会执行提交事务的逻辑,这样addGood()就被提交了。

到此这篇关于spring的事务传播属性REQUIRED_NESTED原理的文章就介绍到这了,更多相关spring REQUIRED_NESTED原理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: spring的事务传播属性REQUIRED_NESTED原理

本文链接: https://www.lsjlt.com/news/214213.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • spring的事务传播属性REQUIRED_NESTED原理
    目录传统事务中回滚点的使用事务的传播属性NESTEDaddAreaAndGood()开启事务addGood()获得事务并创建回滚点addGood()提交事务时释放回滚点addArea...
    99+
    2023-05-20
    spring 事务传播 事务传播属性 REQUIRED_NESTED 原理
  • spring的事务传播属性REQUIRED_NESTED的原理介绍
    这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原理介绍,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。传统事务中回滚点的使用package com.morris.spring.dem...
    99+
    2023-07-06
  • spring的事务传播属性有哪些
    在Spring中,事务传播属性定义了一个方法的事务边界如何与其他方法的事务边界相互关联。Spring提供了以下的事务传播属性:1. ...
    99+
    2023-09-13
    spring
  • Spring中事务的传播属性总结
    本篇内容主要讲解“Spring中事务的传播属性总结”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring中事务的传播属性总结”吧!我们用Spring时,很多时候都会用到他的声明式事务,简单的...
    99+
    2023-06-03
  • 关于Spring事务隔离、传播属性与@Transactional注解
    mysql默认的隔离级别是repeatable_read 根据spring文档,数据库一共有4个隔离级别 read_uncommitread_commited读已提交 ,解决了...
    99+
    2023-05-20
    spring事务隔离 Spring传播属性 Spring@Transactional
  • Spring事务的传播特性有哪些
    本文小编为大家详细介绍“Spring事务的传播特性有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring事务的传播特性有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识...
    99+
    2022-10-19
  • Spring事物的传播特性详解
    目录一、事务的传播性二、测试前准备2.1、准备好数据库表2.2、初始化spring项目2.3、数据库连接信息配置2.4、Service、Dao2.5、测试类2.6、说明三、使用其他传...
    99+
    2022-11-12
  • Spring中事务传播特性的示例分析
    这篇文章主要介绍Spring中事务传播特性的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、使用方式可以采用Transactional,配置propagation即可。打开org.springframewo...
    99+
    2023-06-15
  • Spring源码解析之事务传播特性
    目录一、使用方式二、getTransaction三、handleExistingTransaction四、NESTED 嵌套事务五、个人理解六、总结一、使用方式 可以采用Transa...
    99+
    2022-11-12
  • Spring框架事务属性中事务隔离级别与传播行为全面讲解
    目录一、事务隔离级别①介绍②使用方式二、事务传播行为①介绍②测试一、事务隔离级别 ①介绍 数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事 ...
    99+
    2022-11-13
    Spring事务隔离级别 Spring事务传播行为
  • Spring是如何给事务实现传播特性的
    这篇文章主要介绍“Spring是如何给事务实现传播特性的”,在日常操作中,相信很多人在Spring是如何给事务实现传播特性的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Spring是如何给事务实现传播特性的...
    99+
    2023-06-16
  • Spring事务的七种传播行为
    目录一、什么是事务传播行为二、事务的传播行为有哪些?一、什么是事务传播行为 什么叫事务传播行为?听起来挺高端的,其实很简单。即然是传播,那么至少有两个东西,才可以发生传播。单体不存在...
    99+
    2022-11-13
  • 关于spring事务传播行为非事务方式的理解
    目录spring事务传播行为非事务方式Spring事务理解和配置1 Spring事务1.1 事务简介1.2 事务的传播行为1.3 编程式事务(需要手动写代码,了解)1.4 声明式事务...
    99+
    2022-11-12
  • 关于spring中事务的传播机制
    目录Spring中的事务准备工作实体类DAO层Service层测试类传播机制REQUIREDREQUIRES_NEWSUPPORTSMANDATORYNOT_SUPPORTEDNEV...
    99+
    2023-05-20
    spring 事务 事务传播机制
  • java spring嵌套事务和事务传播类型怎么理解
    本篇内容主要讲解“java spring嵌套事务和事务传播类型怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java spring嵌套事务和事务传播类型怎么理解”吧!  一个有事务的方法...
    99+
    2023-06-02
  • 老生常谈spring的事务传播机制
    目录spring的事务传播机制1、why为什么会有事务传播机制?2、传播机制生效的条件解决方案3、传播机制类型PROPAGATION_REQUIRED (默认)REQUIRES_NE...
    99+
    2022-11-12
  • 深入了解Spring的事务传播机制
    目录Spring 事务传播机制有哪些?事务传播机制使用与演示REQUIRED 使用演示REQUIRED_NEW 使用演示NESTED 使用演示总结Spring 事务传播机制是指,包含...
    99+
    2022-11-13
  • 深入理解Spring事务及传播机制之原理解析与实际应用
    目录事务概述事务管理事务传播机制事务传播机制实现框架源码解析总结Spring 框架是一个流行的Java应用程序框架,其中事务管理是其最重要的特性之一。事务是指一系列相关操作的集合,如...
    99+
    2023-05-16
    Spring事务及传播机制 Spring事务管理 Spring传播机制
  • 一文解析spring中事务的传播机制
    今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。Spring中的事务Spring的事务其实就是数据库的事务操作,符合ACID标...
    99+
    2023-07-06
  • Spring事务的七种传播行为是什么
    本篇内容介绍了“Spring事务的七种传播行为是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、什么是事务传播行为什么叫事务传播行为?...
    99+
    2023-06-30
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作