zoukankan      html  css  js  c++  java
  • Spring 如何在一个事务中开启另一个事务?

    作者:Mazin
    https://my.oschina.net/u/3441184/blog/893628

    这样的情景可能不常见,但是还是会有的,一旦遇到,如果业务比较复杂,就会很麻烦,但是还是有解决的方案的,比如将一个service方法拆成两个方法,也就是将两个操作的事务分开。

    但是这只适用与业务比较简单的,如果出现多次数据库的写操作,而我们调用的系统只需要其中一个写操作的最新数据,如果我们将它分开,那么如果调用目标系统出现异常的时候,那么之前的写操作就不能回滚了。

    举个简单的例子:

    @Service
    public class ServiceA {
    
      @Transactional
      public void doSomething(){
    
        向数据库中添加数据;
    
        调用其他系统;
      }
    }
    

    这里就用伪代码来做示例了,当我们执行了“向数据库中添加数据”,我们去数据库中查询,发现并没有我们添加的数据,但是当我们的service这个方法执行完成之后,数据库中就有这条数据了,这是由于数据库的隔离性造成的。

    Spring中的事务注解 @transactional 提供了一个参数:

    Propagation propagation() default Propagation.REQUIRED;
    

    这个参数是定义 Spring事务的传递性的,默认值为:required,也就是如果有事务,就加入事务,如果没有,就创建事务。

    这个参数的值有很多,例如:REQUIRES_NEW,这个值就代表创建一个新的事务,与原来的事务分开。这个好像能解决我们的问题。关注Java技术栈公众号在后台回复:spring,可获取一份栈长整理的最新 Spring 系列技术干货。

    我们将刚刚那个方法修改一下:

    @Service
    public class ServiceA {
    
      @Transactional
      public void doSomething(){
    
        insert();
    
        调用其他系统;
      }
    
      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public void insert(){
        向数据库中添加数据;
      }
    }
    

    执行之后,发现结果还是没有改变,必须要整体执行完成,数据库中数据才会出现,说明还是在一个事务中。Spring的核心思想,推荐你看看。

    我们再将代码修改一下:

    @Service
    public class ServiceA {
    
      @Autowired
      private ServiceB serviceB;
      @Transactional
      public void doSomething(){
    
        serviceB.insert();
    
        调用其他系统;
      }
    }
    @Service
    public class ServiceB {
    
      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public void insert(){
        向数据库中添加数据;
      }
    }
    

    我们将要事务分离出来的方法写在另一个service中,再次测试,发现执行完插入语句之后,数据库中就已经能查到数据了,说明事务分离了,完成了我们的需求。

    当然** Spring**其实也考虑这个,在 Spring的配置中,我们只需要添加标签:

    aop:aspectj-autoproxy expose-proxy="true"/
    

    或者:

    aop:config expose-proxy="true"
    

    并且在代码的调用中要求使用代理对象去调用即可:

    ((ServiceA ) AopContext.currentProxy()).insert();
    

    关注公众号Java技术栈回复"面试"获取我整理的2020最全面试题及答案。

    推荐去我的博客阅读更多:

    1.Java JVM、集合、多线程、新特性系列教程

    2.Spring MVC、Spring Boot、Spring Cloud 系列教程

    3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

    4.Java、后端、架构、阿里巴巴等大厂最新面试题

    觉得不错,别忘了点赞+转发哦!

  • 相关阅读:
    前端学习之JavaScript
    前端学习之CSS
    前端学习之HTML
    MySQL多表查询(重要)
    C# 基本语法
    第 9 章 —— 原型模式
    第 7 章 —— 代理模式
    第 6 章 —— 装饰模式
    将搜索关键词加红
    SQL Server 创建触发器(trigger)
  • 原文地址:https://www.cnblogs.com/javastack/p/13255810.html
Copyright © 2011-2022 走看看