zoukankan      html  css  js  c++  java
  • Spring事务的传播属性

    前言

    Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可以为我们的开发工作提供许多便利。但是人们对他的误解也颇多,你一定也听过“service方法事务最好不要嵌套”的传言。要想正确的使用工具首先需要了解工具。

    基础概念

    1. 什么是事务传播行为?

    事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。

    用伪代码说明:

    1 @Transaction(Propagation=XXX)
    2  public void methodA(){
    3     methodB();
    4     //doSomething
    5  }
    6  
    7  public void methodB(){
    8     //doSomething
    9  }

    methodA中存在事务,他又调用了methodB。methodB事物的一些特性由methodA决定,这就是事务的传播行为。

    2. Spring中七种事务传播行为

    事务传播行为类型说明
    PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
    PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
    PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
    PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
    PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
    PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

    定义非常简单,也很好理解,下面我们就进入代码测试部分,验证我们的理解是否正确。

    代码验证

    第一种情况。内部均为 propagation = Propagation.REQUIRED

     1 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
     2 @Override
     3 public void testTransactional() {
     4     int insert = downloadImgDao.test1();
     5     log.info("insert1 = {}", insert);
     6 
     7     insert = downloadImgDao.test2();
     8     log.info("insert2 = {}", insert);
     9 }
    10 
    11 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    12 @Override
    13 public int test1() {
    14     DownloadImg downloadImg = new DownloadImg();
    15     downloadImg.setId(666L);
    16     downloadImg.setLink("张三");
    17     downloadImg.setLinkname("16");
    18     int res = downloadImgMapper.insertSelective(downloadImg);
    19     log.info("res1 = {}", res);
    20     return res;
    21 }
    22 
    23 
    24 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    25 @Override
    26 public int test2() {
    27     DownloadImg downloadImg = new DownloadImg();
    28     downloadImg.setId(888L);
    29     downloadImg.setLink("李四");
    30     downloadImg.setLinkname("18");
    31     int res = downloadImgMapper.insertSelective(downloadImg);
    32     log.info("res2 = {}", res);
    33 
    34     int i = 5 / 0;
    35     return res;
    36 }

    张三,李四插入均失败。

    第二种情况。内部一种为 propagation = Propagation.REQUIRED,一种为Propagation.REQUIRES_NEW

     1 @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.REPEATABLE_READ)
     2 @Override
     3 public int test1() {
     4     DownloadImg downloadImg = new DownloadImg();
     5     downloadImg.setId(666L);
     6     downloadImg.setLink("张三");
     7     downloadImg.setLinkname("16");
     8     int res = downloadImgMapper.insertSelective(downloadImg);
     9     log.info("res1 = {}", res);
    10     return res;
    11 }
    12 
    13 
    14 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    15 @Override
    16 public int test2() {
    17     DownloadImg downloadImg = new DownloadImg();
    18     downloadImg.setId(888L);
    19     downloadImg.setLink("李四");
    20     downloadImg.setLinkname("18");
    21     int res = downloadImgMapper.insertSelective(downloadImg);
    22     log.info("res2 = {}", res);
    23 
    24     int i = 5 / 0;
    25     return res;
    26 }

    张三插入成功,李四插入失败。

    第三种情况。内部均为Propagation.REQUIRES_NEW

    跟我们现象的是一样的,如果哪个test异常,哪个就失败,无异常的就成功。

    还有一种情况是,外围抛异常了,内部都不抛异常,两种内部插入也都会成功。

    结论

    本程序是实验了PROPAGATION_REQUIRED以及Propagation.REQUIRES_NEW。

    事务默认以PROPAGATION_REQUIRED来隔离。

    1: 如果内部是PROPAGATION_REQUIRED隔离级别,内部只要一个方法出错,那么整个事务都会回滚。

    2: 如果内部有方法以Propagation.REQUIRES_NEW来隔离。那么他会创建一个新的事务来运行,如果他抛异常了,并不会影响其他事务的以及外部的事务。

    spring事务官方文档:https://docs.spring.io/spring/docs/5.2.6.RELEASE/spring-framework-reference/data-access.html#tx-propagation

    参考文档:https://segmentfault.com/a/1190000013341344

  • 相关阅读:
    SpringCloud------熔断与降级
    Linux中的defunct进程(僵尸进程)
    网站论坛收藏
    同步与阻塞,异步与非阻塞的区别
    Linux下批量杀掉筛选进程
    MapReduce运行原理和过程
    TF-IDF原理
    如何解决VMware 虚拟机不能铺满屏幕
    桥接和nat连接
    http: server gave HTTP response to HTTPS client & Get https://192.168.2.119/v2/: dial tcp 192.168.2.119:443: getsockopt: connection refused
  • 原文地址:https://www.cnblogs.com/wenbochang/p/13050801.html
Copyright © 2011-2022 走看看