其他分享
首页 > 其他分享> > Spring的事务传播机制(大白话)

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

作者:互联网

什么叫做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