Spring中事务传播特性的示例分析

这篇文章主要介绍Spring中事务传播特性的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

一、使用方式

可以采用Transactional,配置propagation即可。打开org.springframework.transaction.annotation.Transactional可见默认传播特性是REQUIRED

Spring中事务传播特性的示例分析

/**
	*Thetransactionpropagationtype.
	*<p>Defaultsto{@linkPropagation#REQUIRED}.
	*@seeorg.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
	*/
	Propagationpropagation()defaultPropagation.REQUIRED;

二、getTransaction

顾名思义,此项属性是在事务存在交互时生效。那么到底是如何生效的呢,核心源码位于org.springframework.transaction.support.AbstractPlatformTransactionManager。核心入口是getTransaction方法。

@Override
	publicfinalTransactionStatusgetTransaction(@NullableTransactionDefinitiondefinition)throwsTransactionException{
		Objecttransaction=doGetTransaction();

		//Cachedebugflagtoavoidrepeatedchecks.
		booleandebugEnabled=logger.isDebugEnabled();

		//
		if(definition==null){
			//Usedefaultsifnotransactiondefinitiongiven.
			definition=newDefaultTransactionDefinition();
		}

		//已经存在事务根据事务传播特性进行处理
		if(isExistingTransaction(transaction)){
			//Existingtransactionfound->checkpropagationbehaviortofindouthowtobehave.
			returnhandleExistingTransaction(definition,transaction,debugEnabled);
		}
		//Checkdefinitionsettingsfornewtransaction.
		if(definition.getTimeout()<TransactionDefinition.TIMEOUT_DEFAULT){
			thrownewInvalidTimeoutException("Invalidtransactiontimeout",definition.getTimeout());
		}

		//Noexistingtransactionfound->checkpropagationbehaviortofindouthowtoproceed.
		//当前不存在事务MANDATORY直接抛出异常
		if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_MANDATORY){
			thrownewIllegalTransactionStateException(
					"Noexistingtransactionfoundfortransactionmarkedwithpropagation'mandatory'");
		}
		//REQUIREDREQUIRES_NEWNESTED则会新建一个事务
		elseif(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRED||
				definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRES_NEW||
				definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NESTED){
			SuspendedResourcesHoldersuspendedResources=suspend(null);
			if(debugEnabled){
				logger.debug("Creatingnewtransactionwithname["+definition.getName()+"]:"+definition);
			}
			try{
				booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);
				DefaultTransactionStatusstatus=newTransactionStatus(
						definition,transaction,true,newSynchronization,debugEnabled,suspendedResources);
				doBegin(transaction,definition);
				prepareSynchronization(status,definition);
				returnstatus;
			}
			catch(RuntimeException|Errorex){
				resume(null,suspendedResources);
				throwex;
			}
		}
		else{
			xxx
		}
	}

可以看到,在当前不存在事务时,

  • MANDATORY 直接抛出异常

  • REQUIRED REQUIRES_NEW NESTED 自动新建一个事务。

那么存在事务时是如何处理的呢?

三、handleExistingTransaction

/**
	*处理已经存在事务的情况
	*CreateaTransactionStatusforanexistingtransaction.
	*/
	privateTransactionStatushandleExistingTransaction(
			TransactionDefinitiondefinition,Objecttransaction,booleandebugEnabled)
			throwsTransactionException{

		//NEVER已经存在事务直接抛出异常
		if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NEVER){
			thrownewIllegalTransactionStateException(
					"Existingtransactionfoundfortransactionmarkedwithpropagation'never'");
		}

		//NOT_SUPPORTED注意prepareTransactionStatus方法参数传递事务的时候传递参数为null,所以是采用非事务方式运行。执行会挂起当前事务。
		if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NOT_SUPPORTED){
			if(debugEnabled){
				logger.debug("Suspendingcurrenttransaction");
			}
			ObjectsuspendedResources=suspend(transaction);
			booleannewSynchronization=(getTransactionSynchronization()==SYNCHRONIZATION_ALWAYS);
			returnprepareTransactionStatus(
					definition,null,false,newSynchronization,debugEnabled,suspendedResources);
		}


		//REQUIRES_NEW新建事务会挂起当前事务
		if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_REQUIRES_NEW){
			if(debugEnabled){
				logger.debug("Suspendingcurrenttransaction,creatingnewtransactionwithname["+
						definition.getName()+"]");
			}
			SuspendedResourcesHoldersuspendedResources=suspend(transaction);
			try{
				booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);
				DefaultTransactionStatusstatus=newTransactionStatus(
						definition,transaction,true,newSynchronization,debugEnabled,suspendedResources);
				doBegin(transaction,definition);
				prepareSynchronization(status,definition);
				returnstatus;
			}
			catch(RuntimeException|ErrorbeginEx){
				resumeAfterBeginException(transaction,suspendedResources,beginEx);
				throwbeginEx;
			}
		}

		//NESTED处理嵌套事务
		if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_NESTED){
			//检查是否支持嵌套事务
			if(!isNestedTransactionAllowed()){
				thrownewNestedTransactionNotSupportedException(
						"Transactionmanagerdoesnotallownestedtransactionsbydefault-"+
						"specify'nestedTransactionAllowed'propertywithvalue'true'");
			}
			if(debugEnabled){
				logger.debug("Creatingnestedtransactionwithname["+definition.getName()+"]");
			}
			//支持的话则采用Savepoint否则开启新事务并不会挂起当前事务
			if(useSavepointForNestedTransaction()){
				//CreatesavepointwithinexistingSpring-managedtransaction,
				//throughtheSavepointManagerAPIimplementedbyTransactionStatus.
				//UsuallyusesJDBC3.0savepoints.NeveractivatesSpringsynchronization.
				DefaultTransactionStatusstatus=
						prepareTransactionStatus(definition,transaction,false,false,debugEnabled,null);
				//注意此处会创建savePoint
				status.createAndHoldSavepoint();
				returnstatus;
			}
			else{
				//Nestedtransactionthroughnestedbeginandcommit/rollbackcalls.
				//UsuallyonlyforJTA:Springsynchronizationmightgetactivatedhere
				//incaseofapre-existingJTAtransaction.
				booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);
				//注意此处newTransaction属性设置为true,说明确实采用了创建新事务方式来实现
				DefaultTransactionStatusstatus=newTransactionStatus(
						definition,transaction,true,newSynchronization,debugEnabled,null);
				doBegin(transaction,definition);
				prepareSynchronization(status,definition);
				returnstatus;
			}
		}
		//AssumablyPROPAGATION_SUPPORTSorPROPAGATION_REQUIRED.
		if(debugEnabled){
			logger.debug("Participatinginexistingtransaction");
		}
		if(isValidateExistingTransaction()){
			if(definition.getIsolationLevel()!=TransactionDefinition.ISOLATION_DEFAULT){
				IntegercurrentIsolationLevel=TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				if(currentIsolationLevel==null||currentIsolationLevel!=definition.getIsolationLevel()){
					ConstantsisoConstants=DefaultTransactionDefinition.constants;
					thrownewIllegalTransactionStateException("Participatingtransactionwithdefinition["+
							definition+"]specifiesisolationlevelwhichisincompatiblewithexistingtransaction:"+
							(currentIsolationLevel!=null?
									isoConstants.toCode(currentIsolationLevel,DefaultTransactionDefinition.PREFIX_ISOLATION):
									"(unknown)"));
				}
			}
			if(!definition.isReadOnly()){
				if(TransactionSynchronizationManager.isCurrentTransactionReadOnly()){
					thrownewIllegalTransactionStateException("Participatingtransactionwithdefinition["+
							definition+"]isnotmarkedasread-onlybutexistingtransactionis");
				}
			}
		}
		booleannewSynchronization=(getTransactionSynchronization()!=SYNCHRONIZATION_NEVER);
		//其他的传播特性则加入当前事务不会创建新事务
		returnprepareTransactionStatus(definition,transaction,false,newSynchronization,debugEnabled,null);
	}

可以看到,当已经存在事务时,

  • NEVER 直接报错,不支持事务

  • NOT_SUPPORTED 默默按照非事务方式运行

  • REQUIRES_NEW 新建一个事务。

  • NESTED 处理嵌套事务 视情况采用savePoint或者新建事务。

  • 其他的 加入当前事务

四、NESTED 嵌套事务

SavePoint

先简单说说SavePoint机制吧。这个也比较简单。比如一个 事务比较复杂,容易出错。那么如果当前DB支持SavePoint的话,那么创建一个SavePoint就等于创建了一个快照,可以不用每次都回滚整个事务,仅回滚到指定的SavePoint即可。

五、个人理解

NESTED这个处理确实比较复杂。个人也查了很多资料。目前个人目前理解如下:NESTED对于事务的处理主要在于级别不同。REQUIRES_NEW创建的两个事务是平级的,一个事务的成功与否对另一个事务的成功与否不产生影响。而NESTED创建的事务则名副其实,是受其父级事务影响的。一句话总结就是,子事务的成功与否不影响父级事务的成功,但是父级事务的成功与否则会影响子事务的成功。父事务回滚,子事务一定会滚。子事务回滚,父事务不一定会滚。

六、总结

最后总结如下

名称说明
PROPAGATION_REQUIRED方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。 默认选项。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。需要JDBC3.0以上支持。

以上是“Spring中事务传播特性的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注恰卡编程网行业资讯频道!

发布于 2021-05-30 14:04:18
收藏
分享
海报
0 条评论
174
上一篇:springboot+VUE如何实现登录注册 下一篇:vue+springboot如何实现登录验证码
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码