Spring 7种事务传播行为
1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
罗列了7种spring的事务传播行为,我们具体来看看它的实现。在这里,我们使用spring annotation注解实现事务。
实现事务的类BusinessServiceImpl
package com.aop; import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivce")
public class BusinessServiceImpl implements IBaseService { @Autowired
IStudentDao studentDao; @Autowired
IBaseServiceB baseServiceb; @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
public String doA() throws Exception {
Student st = new Student();
st.setId(1);
st.setSex("girl");
st.setUsername("zx");
studentDao.insertStudent(st); System.out.println(baseServiceb);
System.out.println("是否是代理调用,AopUtils.isAopProxy(baseServiceb) : " + AopUtils.isAopProxy(baseServiceb));
System.out
.println("是否是cglib类代理调用,AopUtils.isCglibProxy(baseServiceb) : " + AopUtils.isCglibProxy(baseServiceb));
System.out.println("是否是jdk动态接口代理调用,AopUtils.isJdkDynamicProxy(baseServiceb) : "
+ AopUtils.isJdkDynamicProxy(baseServiceb)); //使用代理调用方法doB()
baseServiceb.doB();
int i = 1 / 0;// 抛出异常,doB()的事务事务回滚
return "success";
} // @Transactional(propagation = Propagation.REQUIRES_NEW, isolation =
// Isolation.DEFAULT, rollbackFor = Exception.class)
// public String doB() throws Exception {
// Student st = new Student();
// st.setId(2);
// st.setSex("girl");
// st.setUsername("zx2");
// studentDao.insertStudent(st);
//
// return "success";
// } }
实现事务的类BusinessServiceImpl
package com.aop; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivceB")
public class BusinessServiceImplB implements IBaseServiceB { @Autowired
IStudentDao studentDao; @Transactional(propagation = Propagation.REQUIRES_NEW,isolation=Isolation.DEFAULT,rollbackFor=Exception.class)
public String doB() throws Exception {
Student st = new Student();
st.setId(2);
st.setSex("girl");
st.setUsername("zx2");
studentDao.insertStudent(st);
return "success";
} }
测试类:
package com.aop; import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.thread.service.IBaseFacadeService; //@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = { "classpath:/spring-ibatis.xml", "classpath:/spring-jdbctemplate.xml" })
public class TestStudentDao { public static void main(String[] args) {
try {
BeanFactory factory = new ClassPathXmlApplicationContext("spring-jdbctemplate.xml");
IBaseService service = (IBaseService) factory.getBean("businessSerivce"); service.doA();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试结果:
om.aop.BusinessServiceImplB@14b75fd9
是否是代理调用,AopUtils.isAopProxy(baseServiceb) : true
是否是cglib类代理调用,AopUtils.isCglibProxy(baseServiceb) : true
是否是jdk动态接口代理调用,AopUtils.isJdkDynamicProxy(baseServiceb) : false
java.lang.ArithmeticException: / by zero
从测试结果可以看到,我们在数据库中成功插入了doB()方法中要插入的数据,而doA()中插入的数据被回滚了,这是因为我们在doB()方法中加入ROPAGATION_REQUIRES_NEW传播行为,doB()创建了属于自己的事务,挂起了doA()中的事务,所以事务B提交了,而事务A因为执行异常插入的数据被回滚了。
如果我们将BusinessServiceImplB做下修改,改为第一种传播行为ROPAGATION_REQUIRED
package com.aop; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivceB")
public class BusinessServiceImplB implements IBaseServiceB { @Autowired
IStudentDao studentDao; @Transactional(propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT,rollbackFor=Exception.class)
public String doB() throws Exception {
Student st = new Student();
st.setId(2);
st.setSex("girl");
st.setUsername("zx2");
studentDao.insertStudent(st);
return "success";
} }
测试结果:
com.aop.BusinessServiceImplB@97c87a4
是否是代理调用,AopUtils.isAopProxy(baseServiceb) : true
是否是cglib类代理调用,AopUtils.isCglibProxy(baseServiceb) : true
是否是jdk动态接口代理调用,AopUtils.isJdkDynamicProxy(baseServiceb) : false
java.lang.ArithmeticException: / by zero
从结果可以看到,我们没有成功插入数据,这是为什么呢?因为我们使用的是第一种传播行为PROPAGATION_REQUIRED ,doB()方法被加入到doA()的事务中,doA()执行时抛出了异常,因为doB()和doA()同属于一个事务,则执行操作被一起回滚了。其实在doB()中我们不加入注解,也等同PROPAGATION_REQUIRED的效果。
接下来我们再来看看第五种传播行为PROPAGATION_NOT_SUPPORTED,我们同样修改B类,如下
package com.aop; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivceB")
public class BusinessServiceImplB implements IBaseServiceB { @Autowired
IStudentDao studentDao; @Transactional(propagation = Propagation.NOT_SUPPORTED,isolation=Isolation.DEFAULT,rollbackFor=Exception.class)
public String doB() throws Exception {
Student st = new Student();
st.setId(2);
st.setSex("girl");
st.setUsername("zx2");
studentDao.insertStudent(st);
return "success";
} }
测试结果:
可以看到doB()方法成功插入了数据。doA()方法中插入的数据被回滚了。这是因为传播行为PROPAGATION_NOT_SUPPORTED是doB()以非事务执行的,并且提交了。所以当doA()的事务被回滚时,doB()的操作没有被回滚。
其他的传播行为就不一一列举了,机制是差不多的。
注意:在上面的实例中,我没有把doB()方法放在类BusinessServiceImpl,而是放在BusinessServiceImplB中,这是因为spring通过扫描所有含有注解的@Trasation的方法,使用aop形成事务增强advise。但是加入增强时是通过代理对象调用方法的形式加入的,如果将doB()方法放在doA()方法直接调用时,在调用doB()方法的时候是通过当前对象来调用doB()方法的,而不是通过代理来调用的doB()方法,这个时候doB()方法上加的事务注解就失效了不起作用。在Spring事务传播行为在内部方法不起作用讲到。
spring配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd"
default-lazy-init="false"> <context:component-scan base-package="com.aop"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 数据 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/lpWeb"/>
<property name="username" value="root"/>
<property name="password" value="root123"/>
</bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name = "dataSource" ref="dataSource"/>
</bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Spring 7种事务传播行为的更多相关文章
- Spring 7种事务传播类型
转载:https://www.cnblogs.com/originate918/p/6226342.html PROPAGATION_REQUIRED及其他6种事务传播行为种类. Spring在Tra ...
- 手把手带你实战下Spring的七种事务传播行为
目录 本文目录 一.什么是事务传播行为? 二.事务的7种传播行为 三.7种传播行为实战 本文介绍Spring的七种事务传播行为并通过代码演示下. 本文目录 一.什么是事务传播行为? 事务传播行为(pr ...
- spring事务:事务控制方式,使用AOP控制事务,七种事务传播行为,声明事务,模板对象,模板对象原理分析
知识点梳理 课堂讲义 1)事务回顾 1.1)什么是事务-视频01 事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败. 1.2)事务的作用 事务特征(ACID) 原子 ...
- Spring7种事务传播行为类型--PROPAGATION_REQUIRED及其他6种事务传播行为种类
PROPAGATION_REQUIRED及其他6种事务传播行为种类,有需要的朋友可以参考下. Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务 ...
- 面试官:说说Spring中的事务传播行为
前言 在开发中,相信大家都使用过Spring的事务管理功能.那么,你是否有了解过,Spring的事务传播行为呢? Spring中,有7种类型的事务传播行为.事务传播行为是Spring框架提供的一种事务 ...
- -手写Spring注解版本&事务传播行为
视频参考C:\Users\Administrator\Desktop\蚂蚁3期\[www.zxit8.com] 0018-(每特教育&每特学院&蚂蚁课堂)-3期-源码分析-手写Spri ...
- spring中的事务传播机制
1.事务的实现思想 在spring中要想某个方法具有事务,只要在方法前加一个@Transactional注解.然后spring就会利用aop思想,在这个方法执行前开启事务, 在方法执行后选择提交事务或 ...
- spring常用的事务传播属性说明
事务Transaction,就是一组操作数据库的动作集合.事务是现代数据库理论中的核心概念之一.如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务.当所有的步骤像一个操作一样被 ...
- Spring的七种事务传播机制
概述 当我们调用一个基于Spring的Service接口方法(如UserService#addUser())时,它将运行于Spring管理的事务环境中,Service接口方法可能会在内部调用其它的Se ...
随机推荐
- (转)开放window是服务器端口——以8080为例
本文记录两个内容: 1.win7下打开端口 2.服务器(2003或者其他老版的系统以2003为例) 测试端口时 可用telnet 命令 侦听端口:C:\Documents and Settings\a ...
- OpenGL秒安装及显示
快毕业了,狂补OpenGL中.... 想当初安装opencv那么麻烦,现在openGL几秒钟就安装好了 注意:这里前提是你建立好了工程,如果连工程都不会建立~~GG 测试代码: 复制到工程进行测试! ...
- 2690036 - SAP HANA 2.0 SPS 03 Database Revision 034
Symptom This is the SAP Release Note for SAP HANA 2.0 Database Revision 034 (2.00.034.00) of the SAP ...
- java容器思维导图
转载自:https://blog.csdn.net/zbdxcyg/article/details/72330833
- 关于windows中在env中执行django-admin.py出现Access is denied.的解决办法
(ll_env) E:\python\learning_log>django-admin.pyAccess is denied. 这个是路径的问题,默认的文件获取路径没能正常获取文件 我使用绝对 ...
- Getting started with C# and GDAL
Getting started with C# and GDAL http://vipassanaandenvironmentalinformatics.blogspot.jp/2013/03/get ...
- 如何解决Android帧动画出现的内存溢出
这几天在做动画的时候,遇到了一个OOM的问题,特此记录下来. 普通实现 实现一个帧动画,最先想到的就是用animation-list将全部图片按顺序放入,并设置时间间隔和播放模式.然后将该drawab ...
- 使用Flex4画图形:圆、矩形、线
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="ht ...
- Python linux 上的管理工具 pyenv 安装, pip 使用, python项目(版本分割, 项目分割, 虚拟环境创建)
01: 假设你有一个最小环境安装的 centos-6.x 的linux操作系统 02: 安装 git => yum -y install git 03: 安装依赖 => yum -y in ...
- Windows下卸载Apache、Mysql
卸载Apache 1. 停止服务 2.以管理员身份打开命令环境 3. 删除Apache文件目录 卸载Mysql 一.在控制面板,卸载MySQL的所有组件控制面板——>所有控制面板项——>程 ...