深入理解Spring事务的传播行为

前言

本文主要介绍下Spring事务中的传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可以为我们的开发工作提供许多便利。

下面话不多说了,来一起看看详细的介绍吧

事务传播行为介绍

Spring中的7个事务传播行为:

|事务行为|说明 |
|:--|:--|
|PROPAGATION_REQUIRED | 支持当前事务,假设当前没有事务。就新建一个事务 |
| PROPAGATION_SUPPORTS |支持当前事务,假设当前没有事务,就以非事务方式运行 |
| PROPAGATION_MANDATORY| 支持当前事务,假设当前没有事务,就抛出异常|
| PROPAGATION_REQUIRES_NEW | 新建事务,假设当前存在事务。把当前事务挂起|
|PROPAGATION_NOT_SUPPORTED | 以非事务方式运行操作。假设当前存在事务,就把当前事务挂起 |
| PROPAGATION_NEVER | 以非事务方式运行,假设当前存在事务,则抛出异常 |
| PROPAGATION_NESTED |如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |

举例说明

案例代码

ServiceA

ServiceA {
  void methodA() {
   ServiceB.methodB();
  }
}

ServiceB

ServiceB {
  void methodB() {
  }
}

1.PROPAGATION_REQUIRED

  假如当前正要运行的事务不在另外一个事务里,那么就起一个新的事务 比方说,ServiceB.methodB的事务级别定义PROPAGATION_REQUIRED, 那么因为执行ServiceA.methodA的时候,ServiceA.methodA已经起了事务。这时调用ServiceB.methodB,ServiceB.methodB看到自己已经执行在ServiceA.methodA的事务内部。就不再起新的事务。而假如ServiceA.methodA执行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在ServiceA.methodA或者在ServiceB.methodB内的不论什么地方出现异常。事务都会被回滚。即使ServiceB.methodB的事务已经被提交,可是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚

2.PROPAGATION_SUPPORTS

  假设当前在事务中。即以事务的形式执行。假设当前不在一个事务中,那么就以非事务的形式执行

3PROPAGATION_MANDATORY

  必须在一个事务中执行。也就是说,他仅仅能被一个父事务调用。否则,他就要抛出异常

4.PROPAGATION_REQUIRES_NEW

  这个就比较绕口了。 比方我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW。那么当运行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起。ServiceB.methodB会起一个新的事务。等待ServiceB.methodB的事务完毕以后,他才继续运行。
他与PROPAGATION_REQUIRED 的事务差别在于事务的回滚程度了。由于ServiceB.methodB是新起一个事务,那么就是存在两个不同的事务。假设ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚。ServiceB.methodB是不会回滚的。假设ServiceB.methodB失败回滚,假设他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。

5.PROPAGATION_NOT_SUPPORTED

  当前不支持事务。比方ServiceA.methodA的事务级别是PROPAGATION_REQUIRED 。而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,那么当执行到ServiceB.methodB时。ServiceA.methodA的事务挂起。而他以非事务的状态执行完,再继续ServiceA.methodA的事务。

6.PROPAGATION_NEVER

  不能在事务中执行。

如果ServiceA.methodA的事务级别是PROPAGATION_REQUIRED。 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,那么ServiceB.methodB就要抛出异常了。

7.PROPAGATION_NESTED

  如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

Spring中事务的配置

配置文件的方式

<tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
  <!--设置所有匹配的方法,然后设置传播级别和事务隔离-->
   <tx:method name="save*" propagation="REQUIRED" />
   <tx:method name="add*" propagation="REQUIRED" />
   <tx:method name="create*" propagation="REQUIRED" />
   <tx:method name="insert*" propagation="REQUIRED" />
   <tx:method name="update*" propagation="REQUIRED" />
   <tx:method name="merge*" propagation="REQUIRED" />
   <tx:method name="del*" propagation="REQUIRED" />
   <tx:method name="remove*" propagation="REQUIRED" />
   <tx:method name="put*" propagation="REQUIRED" />
   <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
   <tx:method name="count*" propagation="SUPPORTS" read-only="true" />
   <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
   <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
   <tx:method name="*" propagation="SUPPORTS" read-only="true" />
  </tx:attributes>
</tx:advice> 

注解的方式

<!--开启注解的方式-->
<tx:annotation-driven transaction-manager="transactioManager" />

@Transactional(propagation=Propagation.REQUIRED)

如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

@Transactional(propagation=Propagation.NOT_SUPPORTED)

容器不为这个方法开启事务

@Transactional(propagation=Propagation.REQUIRES_NEW)

不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务

@Transactional(propagation=Propagation.MANDATORY)

必须在一个已有的事务中执行,否则抛出异常

@Transactional(propagation=Propagation.NEVER)

必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)

@Transactional(propagation=Propagation.SUPPORTS)

如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • SpringBoot thymeleaf eclipse热部署方案操作步骤

    网上找了好多的springboot热部署方案,也尝试了好几种方法,下面是我的成功方案跟大家分享 操作步骤 1.pom中添加热部署依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency&g

  • SpringSessionRedis配置及发现的问题讲解

    最近写项目,需要把session放入Redis中,来实现分布式.我本来要用Tomcat部署Redis这种方法,但是依赖于容器了.无意中发现了SpringSession,这可挺不错的,写完了发现不好用,问度娘也没弄明白,最后我写了2个demo一个springMVC的,一个spring整合struts2的,发现SpringSession需要SpringMVC的支持.也就是说我的项目用不了了. 先说说springsession的配置吧: 一.Maven中pom.xml文件中添加(选一种添加上就行):

  • Spring Boot中使用Spring-data-jpa的配置方法详解

    为了解决这些大量枯燥的数据操作语句,我们第一个想到的是使用ORM框架,比如:hibernate.通过整合Hibernate之后,我们以操作Java实体的方式最终将数据改变映射到数据库表中. 为了解决抽象各个Java实体基本的"增删改查"操作,我们通常会以泛型的方式封装一个模板Dao来进行抽象简化,但是这样依然不是很方便,我们需要针对每个实体编写一个继承自泛型模板Dao的接口,再编写该接口的实现.虽然一些基础的数据访问已经可以得到很好的复用,但是在代码结构上针对每个实体都会有一堆Dao的

  • mysql+spring+mybatis实现数据库读写分离的代码配置

    场景:一个读数据源一个读写数据源. 原理:借助spring的[org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource]这个抽象类实现,看名字可以了解到是一个路由数据源的东西,这个类中有一个方法 /** * Determine the current lookup key. This will typically be * implemented to check a thread-bound transaction

  • springmvc配置线程池Executor做多线程并发操作的代码实例

    加载xml文件 在ApplicationContext.xml文件里面添加 xmlns:task="http://www.springframework.org/schema/task" xmlns文件并且xsi:schemaLocation中添加 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd 在spring中配置Executor

  • Spring集成jedis的配置与使用简单实例

    jedis是redis的java客户端,spring将redis连接池作为一个bean配置. redis连接池分为两种,一种是"redis.clients.jedis.ShardedJedisPool",这是基于hash算法的一种分布式集群redis客户端连接池. 另一种是"redis.clients.jedis.JedisPool",这是单机环境适用的redis连接池. maven导入相关包: <!-- redis依赖包 --> <depende

  • Spring线程池ThreadPoolExecutor配置并且得到任务执行的结果

    用ThreadPoolExecutor的时候,又想知道被执行的任务的执行情况,这时就可以用FutureTask. ThreadPoolTask package com.paul.threadPool; import java.io.Serializable; import java.util.concurrent.Callable; public class ThreadPoolTask implements Callable<String>, Serializable { private s

  • Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理,另一种是CGLib的方式. 自Java 1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,后来这项技术被用到了Spring的很多地方. JDK动态代理主要涉及java.lang.reflect包下边的两个类:Proxy和InvocationHandler.其中,Invoc

  • Spring boot配置文件加解密详解

    功能介绍 大家都知道在Spring boot开发过程中,需要在配置文件里配置许多信息,如数据库的连接信息等,如果不加密,传明文,数据库就直接暴露了,相当于"裸奔"了,因此需要进行加密处理才行. 在项目中使用jasypt-1.9.4.jar包,能够实现对明文进行加密,对密文进行解密.配置相关加密信息,就能够实现在项目运行的时候,自动把配置文件中已经加密的信息解密成明文,供程序使用 下面话不多说了,来一起看看详细的介绍吧 使用说明 1.pom引入依赖 <dependency>

  • Spring框架十一种常见异常的解决方法汇总

    在程序员生涯当中,提到最多的应该就是SSH三大框架了.作为第一大框架的Spring框架,我们经常使用. 然而在使用过程中,遇到过很多的常见异常,我在这里总结一下,大家共勉. 一.找不到配置文件的异常 org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [com/herman/ss/controller];

随机推荐