zoukankan      html  css  js  c++  java
  • 云笔记项目-Spring事务学习-传播Requried

    在准备好前期的项目搭建后,接下来就一个个的测试,首先测试事务传播的Required

    Service层两个实现类

    Service层两个实现类,只是更换了方法事务传播的属性,其他都一样,后续测试也只修改传播的属性即可,这里只列一次便于理解。

     1 package Service;
     2 
     3 import javax.annotation.Resource;
     4 
     5 import org.springframework.stereotype.Service;
     6 import org.springframework.transaction.annotation.Propagation;
     7 import org.springframework.transaction.annotation.Transactional;
     8 
     9 import DAO.EmpDAO;
    10 import Entity.EMP;
    11 
    12 @Service("service1")
    13 public class EMPService1Impl implements EMPService1{
    14     
    15     @Resource(name="empDAO")
    16     EmpDAO dao;
    17     
    18     @Transactional(propagation=Propagation.REQUIRED)
    19     public void addEmp1(EMP emp) {
    20         dao.addEMP1(emp);        
    21     }
    22 
    23 }
     1 package Service;
     2 
     3 import javax.annotation.Resource;
     4 
     5 import org.springframework.stereotype.Service;
     6 import org.springframework.transaction.annotation.Propagation;
     7 import org.springframework.transaction.annotation.Transactional;
     8 
     9 import DAO.EmpDAO;
    10 import Entity.EMP;
    11 
    12 @Service("service2")
    13 public class EMPService2Impl implements EMPService2{
    14     
    15     @Resource(name="empDAO")
    16     EmpDAO dao;
    17    
    18     @Transactional(propagation=Propagation.REQUIRED)
    19     public void addEmp2(EMP emp) {
    20         dao.addEMP2(emp);
    21     }
    22     
    23     @Transactional(propagation=Propagation.REQUIRED)
    24     public void addEmp2WithException(EMP emp) {
    25         dao.addEMP2(emp);
    26         throw new RuntimeException();
    27     }
    28 
    29 }

    LayerT层代码

     1 package LayerT;
     2 
     3 import javax.annotation.Resource;
     4 
     5 import org.springframework.stereotype.Component;
     6 import org.springframework.transaction.annotation.Propagation;
     7 import org.springframework.transaction.annotation.Transactional;
     8 
     9 import Entity.EMP;
    10 import Service.EMPService1;
    11 import Service.EMPService2;
    12 
    13 /**
    14  * 测试Required
    15  * @author yangchaolin
    16  *
    17  */
    18 @Component("requiredTest")
    19 public class RequiredTest {
    20     @Resource(name="service1")
    21     EMPService1 service1;
    22     @Resource(name="service2")
    23     EMPService2 service2;
    24     
    25     /**
    26      * 外层方法没有事务,但是抛出异常
    27      * @param emp1
    28      * @param emp2
    29      */
    30     public void testRequiredWithoutTransaction1(EMP emp1,EMP emp2) {
    31         service1.addEmp1(emp1);
    32         service2.addEmp2(emp2);
    33         throw new RuntimeException();
    34     }
    35     /**
    36      * 外层方法没有事务,内层有方法抛出异常
    37      * @param emp1
    38      * @param emp2
    39      */
    40     public void testRequiredWithoutTransaction2(EMP emp1,EMP emp2) {
    41         service1.addEmp1(emp1);
    42         service2.addEmp2WithException(emp2);
    43     }
    44     /**
    45      * 外层方法有事务,但是抛出异常
    46      * @param emp1
    47      * @param emp2
    48      */
    49     @Transactional(propagation=Propagation.REQUIRED)
    50     public void testRequiredWithTransaction1(EMP emp1,EMP emp2) {
    51         service1.addEmp1(emp1);
    52         service2.addEmp2(emp2);
    53         throw new RuntimeException();
    54     }
    55     /**
    56      * 外层方法有事务,内层有方法抛出异常
    57      * @param emp1
    58      * @param emp2
    59      */
    60     @Transactional(propagation=Propagation.REQUIRED)
    61     public void testRequiredWithTransaction2(EMP emp1,EMP emp2) {
    62         service1.addEmp1(emp1);
    63         service2.addEmp2WithException(emp2);
    64     }    
    65     /**
    66      * 外层方法有事务,内存方法抛出的异常被捕获
    67      * @param emp1
    68      * @param emp2
    69      */
    70     @Transactional(propagation=Propagation.REQUIRED)
    71     public void testRequiredWithTransaction3(EMP emp1,EMP emp2) {
    72         service1.addEmp1(emp1);
    73         try {
    74         service2.addEmp2WithException(emp2);
    75         }catch(Exception e) {
    76             System.out.println("回滚");
    77         }
    78     }
    79     
    80 }

    测试代码

    其中baseTest为父类,里面读取Spring-MVC.xml和Spring-Mybatis配置文件后初始化了ApplicationContext,继承它后后续其他事务传播属性的测试就不需要重复写这一部分代码。

     1 package TestCase;
     2 
     3 import org.junit.Test;
     4 
     5 import Entity.EMP;
     6 import LayerT.RequiredTest;
     7 
     8 public class requiredTestCase extends baseTest{
     9     @Test
    10     public void test1() {
    11         RequiredTest T1=ac.getBean("requiredTest",RequiredTest.class);
    12         EMP emp1=new EMP("张三",18);
    13         EMP emp2=new EMP("李四",28);
    14         T1.testRequiredWithoutTransaction1(emp1, emp2);
    15       }    
    16     @Test
    17     public void test2() {
    18         RequiredTest T1=ac.getBean("requiredTest",RequiredTest.class);
    19         EMP emp1=new EMP("张三",18);
    20         EMP emp2=new EMP("李四",28);
    21         T1.testRequiredWithoutTransaction2(emp1, emp2);
    22       }    
    23     @Test
    24     public void test3() {
    25         RequiredTest T1=ac.getBean("requiredTest",RequiredTest.class);
    26         EMP emp1=new EMP("张三",18);
    27         EMP emp2=new EMP("李四",28);
    28         T1.testRequiredWithTransaction1(emp1, emp2);
    29       }    
    30     @Test
    31     public void test4() {
    32         RequiredTest T1=ac.getBean("requiredTest",RequiredTest.class);
    33         EMP emp1=new EMP("张三",18);
    34         EMP emp2=new EMP("李四",28);
    35         T1.testRequiredWithTransaction2(emp1, emp2);
    36       }     
    37     @Test
    38     public void test5() {
    39         RequiredTest T1=ac.getBean("requiredTest",RequiredTest.class);
    40         EMP emp1=new EMP("张三",18);
    41         EMP emp2=new EMP("李四",28);
    42         T1.testRequiredWithTransaction3(emp1, emp2);
    43       }         
    44 }

    (1)外层方法没有事务测试结果

    test1 张三插入,李四插入
    test2 张三插入,李四未插入

    结论:在外层方法没有开启事务的情况下,传播属性为Required的方法,会各自执行事务,互不干扰,当方法出现异常时,会出现回滚,如李四就未插入。

    (2)外层方法有事务测试结果

    test3 张三未插入,李四未插入
    test4 张三未插入,李四未插入
    test5 张三未插入,李四未插入

    结论:在外层方法开启事务,并且传播属性为默认Required的时候,内层方法与外层方法事务传播属性一样,会将事务绑定在一起,不论是外层还是内层方法出现异常,都会导致数据回滚,即使将内层抛出异常的方法捕获也没有用。

    参考博客:https://segmentfault.com/a/1190000013341344

  • 相关阅读:
    OpenID Connect 验证
    升级到 .NET Core 3.1
    深入 .NET Core 基础
    依赖注入在 dotnet core 中实现与使用:3 使用 Lazy<T> 延迟实例化
    依赖注入在 dotnet core 中实现与使用:2 使用 Extensions DependencyInjection
    依赖注入在 dotnet core 中实现与使用:1 基本概念
    ng-bootstrap 组件集中 tabset 组件的实现分析
    一笔百亿美元军方订单,引发了美国科技公司大混战
    4种事务的隔离级别,InnoDB怎样巧妙实现?
    Google I/O 官方应用中的动效设计
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/10628776.html
Copyright © 2011-2022 走看看