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>

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值