一、PROPAGATION_REQUIRED:若是当前没有事务,就建立一个新事务,若是当前存在事务,就加入该事务,该设置是最经常使用的设置。java
二、PROPAGATION_SUPPORTS:支持当前事务,若是当前存在事务,就加入该事务,若是当前不存在事务,就以非事务执行。‘mysql
三、PROPAGATION_MANDATORY:支持当前事务,若是当前存在事务,就加入该事务,若是当前不存在事务,就抛出异常。spring
四、PROPAGATION_REQUIRES_NEW:建立新事务,不管当前存不存在事务,都建立新事务。sql
五、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。数据库
六、PROPAGATION_NEVER:以非事务方式执行,若是当前存在事务,则抛出异常。apache
七、PROPAGATION_NESTED:若是当前存在事务,则在嵌套事务内执行。若是当前没有事务,则执行与PROPAGATION_REQUIRED相似的操做。测试
罗列了7种spring的事务传播行为,咱们具体来看看它的实现。在这里,咱们使用spring annotation注解实现事务。url
实现事务的类BusinessServiceImplspa
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"; // } }
实现事务的类BusinessServiceImpl3d
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>