ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring的事务传播机制(大白话)

2022-01-15 14:00:24  阅读:501  来源: 互联网

标签:事务 大白话 Spring 当前 Mysql 执行 方法


什么叫做Spring的事务机制?

Spring自身没没有什么事务机制,只是连接的是Mysql这样的支持事务的数据库时,在对Mysql数据库进行一系列的增删改操作的时候,就需要合理使用Mysql的事务机制。

Spring的事务实现方式是通过AOP实现的,比如一个A方法上面标注了@Transactional,A方法里面有对Mysql数据库的操作,那么通过AOP实现事务的方式就是:在执行A方法之前发出begin trancation,在执行A方法之后,如果没有报错,就发出commit,如果有报错就发出rollback给Mysql。

那么所谓的Spring的事务机制,就是说如何把begin transaction、commit 、rollback这些sql语句在"合适的时机"发给Mysql,OK,那么对这个“合适的实际”的把控与管理,就叫做Spring的事务机制了。

那什么又叫做Spring的事务传播机制呢?

比如代码中A方法调用了B方法,A方法、B方法上都标注了@Transactional,那么问题来了:A方法里对发给Mysql的sql语句应该和B方法里的在一个事务里吗?也就是说是在A方法、B方法执行之前都发begin transaction,执行之后都发commit,还是说只需要在A方法执行之前发begin transaction,在A方法执行之后发rollback呢?好,如何处理这样的问题,这就是Spring的事务传播机制。

Spring传播机制:

查看@Transactional的源码:

 其中Propagation指的是事务传播方式的枚举类,点进去看看:

 这便是Spring事务传播机制的几种方式了,以下一一进行介绍:

REQUIRED

如果当前没有事务,则新建一个事务;如果当前有事务,则加入当前事务。这是默认的传播方式。

比如A方法调用了B方法,其中B方法标注了@Transactional,如果A方法当前没有事务,就在执行B方法的时候新建一个事务,也就是通过AOP,在执行B方法之前发一个begin transaction给Mysql,在执行B方法之后发一个commit给Mysql(如果执行没有报错的话);如果A方法当前已经在一个事务中了,那么在执行B方法前后不做任何处理。

REQUIRES_NEW

无论当前是否存在事务,都要新建事务。如果当前存在事务,把当前事务挂起,当把新建的事务执行完毕并提交之后,再把当前事务从挂起中恢复出来,继续执行。

比如A方法调用了B方法,其中B方法标注了@Transactional(propagation = Propagation.REQUIRES_NEW),那么无论当前是否存在事务,会通过AOP的方式,在执行B方法之前发一个begin transaction 给Mysql,在执行B方法之后,发一个commit给Mysql(如果执行没有报错的话)。

NESTED

嵌套事务。如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则新建一个事务。

这里说“嵌套”其实是Spring的说法,因为方法调用的缘由吧,其实实际依赖的是Mysql的savepoint、rollback to,在Mysql看来,更像是在一个事务中回滚到某个保存点。

比如A方法调用B方法,其中B方法标注了@Transactional(propagation = Propagation.NESTED),如果A方法没有事务,则在执行B方法之前发出begin transaction,执行之后发送commit(如果执行没有报错的话);如果A方法有事务,则在执行B方法之前发出savepoint x;在执行B方法之后,如果顺利,则什么都不做,如果在执行B方法中抛出了异常(默认为RuntimeException),则发出rollback to x;

SUPPORTS

支持当前事务。如果当前没有事务,就以非事务方式执行;如果当前有事务,则加入。

比如A方法调用了B方法,其中B方法上标注了@Transactional(propagation = Propagation.SUPPORTS),不管A方法有没有事务,在执行B方法前后都不做任何处理。

MANDATORY

使用当前的事务。如果当前没有事务,就抛出异常;如果当前有事务,则加入。

比如A方法调用了B方法,其中B方法上标注了@Transactional(propagation = Propagation.MANDATORY),如果A方法有事务,则执行B方法前后不做任何处理,如果A方法没有事务,则通过AOP的方式,在执行B方法之前抛出指定的异常。

NOT_SUPPORTED

以非事务方式执行。如果当前没有事务,则正常执行;如果当前存在事务,就把当前事务挂起。

NEVER

以非事务方式执行。如果当前没有事务,则正常执行;如果当前存在事务,则抛出异常。

嵌套事务的意义:

如果程序正常执行,没有抛出RuntimeException,也就不会涉及到回滚,那么嵌套事务不会有特殊之处,NESTED的特殊之处,在于涉及到回滚的场景:A方法调用B方法,其中B方法标注了@Transactional(propagation = Propagation.NESTED),如果B方法抛出RuntimeException,那么只会对B方法中的操作进行回滚,而不影响到A方法中的其他操作。

好,利用这个特性,就可以使用在某些场景中,比如:A方法中调用了B方法、C方法,如果B方法执行失败,则调用C方法。实现方式就是:如果B方法执行失败,对B方法进行回滚,同时A方法并不回滚,在A方法代码中捕获这个异常,然后在异常分支中调用C方法。

局限性:

Spring事务机制只限于单应用内,不支持分布式事务!

标签:事务,大白话,Spring,当前,Mysql,执行,方法
来源: https://blog.csdn.net/weixin_35794878/article/details/122508596

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有