接下来测试事务传播属性NESTED
Service层
Service层方法事务传播属性都设置为NESTED。
LayerT层代码
1 package LayerT; 2 3 import javax.annotation.Resource; 4 5 import org.springframework.stereotype.Component; 6 import org.springframework.transaction.annotation.Transactional; 7 8 import Entity.EMP; 9 import Service.EMPService1; 10 import Service.EMPService2; 11 /** 12 * 测试Nested 13 * @author yangchaolin 14 * 15 */ 16 @Component("nestedTest") 17 public class NestedTest { 18 @Resource(name="service1") 19 EMPService1 service1; 20 @Resource(name="service2") 21 EMPService2 service2; 22 /** 23 * 外层方法没有事务,但是抛出异常 24 * @param emp1 25 * @param emp2 26 */ 27 public void testNestedWithoutTransaction1(EMP emp1,EMP emp2) { 28 service1.addEmp1(emp1); 29 service2.addEmp2(emp2); 30 throw new RuntimeException(); 31 } 32 /** 33 * 外层方法没有事务,内层方法抛出异常 34 * @param emp1 35 * @param emp2 36 */ 37 public void testNestedWithoutTransaction2(EMP emp1,EMP emp2) { 38 service1.addEmp1(emp1); 39 service2.addEmp2WithException(emp2); 40 } 41 /** 42 * 外层方法有事务,并且抛出异常 43 * @param emp1 44 * @param emp2 45 */ 46 @Transactional //默认为传播属性为Required 47 public void testNestedWithTransaction1(EMP emp1,EMP emp2) { 48 service1.addEmp1(emp1); 49 service2.addEmp2(emp2); 50 throw new RuntimeException(); 51 } 52 /** 53 * 外层方法有事务,内层方法抛出异常 54 * @param emp1 55 * @param emp2 56 */ 57 @Transactional //默认为传播属性为Required 58 public void testNestedWithTransaction2(EMP emp1,EMP emp2) { 59 service1.addEmp1(emp1); 60 service2.addEmp2WithException(emp2); 61 } 62 /** 63 * 外层方法有事务,内层方法抛出的异常被捕获 64 * @param emp1 65 * @param emp2 66 */ 67 @Transactional //默认为传播属性为Required 68 public void testNestedWithTransaction3(EMP emp1,EMP emp2) { 69 service1.addEmp1(emp1); 70 try { 71 service2.addEmp2WithException(emp2); 72 }catch(Exception e) { 73 System.out.println("回滚"); 74 } 75 } 76 }
测试代码
1 package TestCase; 2 3 import org.junit.Test; 4 5 import Entity.EMP; 6 import LayerT.NestedTest; 7 import LayerT.RequiredTest; 8 9 public class nestedTestCase extends baseTest{ 10 @Test 11 public void test1() { 12 NestedTest T1=ac.getBean("nestedTest",NestedTest.class); 13 EMP emp1=new EMP("张三",18); 14 EMP emp2=new EMP("李四",28); 15 T1.testNestedWithoutTransaction1(emp1, emp2); 16 } 17 @Test 18 public void test2() { 19 NestedTest T1=ac.getBean("nestedTest",NestedTest.class); 20 EMP emp1=new EMP("张三",18); 21 EMP emp2=new EMP("李四",28); 22 T1.testNestedWithoutTransaction2(emp1, emp2); 23 } 24 @Test 25 public void test3() { 26 NestedTest T1=ac.getBean("nestedTest",NestedTest.class); 27 EMP emp1=new EMP("张三",18); 28 EMP emp2=new EMP("李四",28); 29 T1.testNestedWithTransaction1(emp1, emp2); 30 } 31 @Test 32 public void test4() { 33 NestedTest T1=ac.getBean("nestedTest",NestedTest.class); 34 EMP emp1=new EMP("张三",18); 35 EMP emp2=new EMP("李四",28); 36 T1.testNestedWithTransaction2(emp1, emp2); 37 } 38 @Test 39 public void test5() { 40 NestedTest T1=ac.getBean("nestedTest",NestedTest.class); 41 EMP emp1=new EMP("张三",18); 42 EMP emp2=new EMP("李四",28); 43 T1.testNestedWithTransaction3(emp1, emp2); 44 } 45 }
测试结果:
(1)外层方法没有事务
test1 | 张三插入,李四插入 |
test2 | 张三插入,李四未插入 |
结论:在外层方法没有事务声明的情况下,内层方法事务传播属性为NESTED时,类似REQUIRED,内层方法之间事务相互独立,互不影响,如果内层方法有异常,会单独回滚自己的事务,不会影响其他事务。
(2)外层方法有事务
test3 | 张三未插入,李四未插入 |
test4 | 张三未插入,李四未插入 |
test5 | 张三插入,李四未插入 |
结论:当外层方法声明默认事务,其传播属性为REQUIRED,内层方法事务传播属性为NESTED的情况下,内层方法事务为外层方法事务的子事务,当外层方法有异常,或者内层方法抛出异常,所以事务都需要回滚,所以test3和test4都没有插入成功。当内层方法被捕获,只会回滚抛出异常的方法事务,其他子事务不受影响。