• spring事务传播特性实验(2):PROPAGATION_REQUIRED实验结果与分析


      本文延续上一文章(spring事务传播特性实验(1):数据准备),在已经准备好环境的情况下,做如下的实验,以验证spring传播特性,加深对spring传播特性的理解。

      本次主要验证PROPAGATION_REQUIRED的传播特性: 

      TransactionDefinition.PROPAGATION_REQUIRED

      TransactionDefinition.PROPAGATION_REQUIRED:根据spring的定义PROPAGATION_REQUIRED即需要事务的支持,如果没有的情况下会自己创建一个新的事务

      我们进行如下测试:

      A、外部有事务的情况下:http://localhost:8080/test1?type=0

    DEBUG  137  DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465] for JDBC transaction
    DEBUG  143  DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465] to manual commit
     INFO  149  INFO  com.sapling.project.module.biz.TransactionTest - [outerTransaction]current transaction name : outerTransaction
     INFO  151  INFO  com.sapling.project.module.biz.TransactionTest - {name:0}
    DEBUG  263  DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Participating in existing transaction
     INFO  263  INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction 0 ]current transaction name : outerTransaction
     INFO  263  INFO  com.sapling.project.module.biz.TransactionTest - {name:0}
     INFO  267  INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction]current transaction outerTransaction commit.
    DEBUG  268  DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
    DEBUG  268  DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465]
    DEBUG  274  DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465] after transaction
    DEBUG  274  DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
     INFO  275  INFO  com.sapling.project.module.biz.TransactionTest - [outerTransaction]current transaction null commit.
    

      从日志中我们可以看到这样的记录:Participating in existing transaction,加入到一个已经存在的事务中。

      数据表插入成功

    +----+----------+------+--------+
    | id | name     | sex  | status |
    +----+----------+------+--------+
    |  8 | 0-true   | NULL |   NULL |
    |  9 | i-0-true | NULL |   NULL |
    

      B、外部没有事务的情况下:http://localhost:8080/test3?type=0

     INFO 093 INFO  com.sapling.project.module.biz.TransactionTest - [outerTransaction] did not have transaction 
     INFO 094 INFO  com.sapling.project.module.biz.TransactionTest - {name:0}
    DEBUG 094 DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
    DEBUG 104 DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
    DEBUG 104 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
    DEBUG 104 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465] for JDBC transaction
    DEBUG 104 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465] to manual commit
     INFO 106 INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction 0 ]current transaction name : null
     INFO 107 INFO  com.sapling.project.module.biz.TransactionTest - {name:0}
    DEBUG 111 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
    DEBUG 111 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465]
    DEBUG 118 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1512c465] after transaction
    DEBUG 119 DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
     INFO 119 INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction]current transaction null commit.
    

       Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,创建一个新的事务,传播特性为PROPAGATION_REQUIRED,隔离级别为默认。

      数据表插入成功

    mysql> select * from sys_user
        -> ;
    +----+----------+------+--------+
    | id | name     | sex  | status |
    +----+----------+------+--------+
    |  8 | 0-true   | NULL |   NULL |
    |  9 | i-0-true | NULL |   NULL |
    | 10 | o-0-true | NULL |   NULL |
    | 11 | i-0-true | NULL |   NULL |
    +----+----------+------+--------+
    4 rows in set (0.00 sec)
    

      C、外部有事务,但内部异常的情况下:

      系统报500错误,日志如下:

    165 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
    172 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5d7163af] for JDBC transaction
    172 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5d7163af] to manual commit
    174 INFO  com.sapling.project.module.biz.TransactionTest - [outerTransaction]current transaction name : outerTransaction
    174 INFO  com.sapling.project.module.biz.TransactionTest - {name:o-0-true}
    178 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Participating in existing transaction
    178 INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction 0 ]current transaction name : outerTransaction
    178 INFO  com.sapling.project.module.biz.TransactionTest - {name:11111111111111111111111111111}
    284 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Participating transaction failed - marking existing transaction as rollback-only
    284 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Setting JDBC transaction [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5d7163af] rollback-only
    284 INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction ]current transaction outerTransaction rollback. 284 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Global transaction is marked as rollback-only but transactional code requested commit 284 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback 284 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5d7163af] 319 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5d7163af] after transaction 319 DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource 326 DEBUG org.springframework.web.servlet.DispatcherServlet - Could not complete request org.springframework.transaction.IllegalTransactionStateException: Transaction is already completed - do not call commit or rollback more than once per transaction

      可以看到,事务在在内部方法中就直接回滚了,整个事务已经完成了,外部事务再在做回滚操作的时候,就报错了,这里可以在回滚操作之前加上!status.isCompleted()检查事务是不是完成了,完成了则不需要再回滚了。

      检查数据库,可以看出事务整个失败了,不管是内部方法还是外部方法的数据都没有插入成功:

    mysql> select * from sys_user;
    +----+----------+------+--------+
    | id | name     | sex  | status |
    +----+----------+------+--------+
    |  8 | 0-true   | NULL |   NULL |
    |  9 | i-0-true | NULL |   NULL |
    | 10 | o-0-true | NULL |   NULL |
    | 11 | i-0-true | NULL |   NULL |
    +----+----------+------+--------+
    4 rows in set (0.00 sec)
    

      D、外部没有事务,内部执行失败:

    .964 INFO  com.sapling.project.module.biz.TransactionTest - [outerTransaction] did not have transaction 
    .964 INFO  com.sapling.project.module.biz.TransactionTest - {name:0-true}
    .964 DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
    .973 DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
    .973 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
    .973 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5b773cec] for JDBC transaction
    .973 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5b773cec] to manual commit
    .974 INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction 0 ]current transaction name : null
    .974 INFO  com.sapling.project.module.biz.TransactionTest - {name:11111111111111111111111111111}
    .978 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
    .978 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5b773cec]
    .982 DEBUG o.s.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5b773cec] after transaction
    .982 DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
    .982 INFO  com.sapling.project.module.biz.TransactionTest - [doInnerTransaction ]current transaction null rollback.

      

      数据库表查询结果:

    mysql> select * from sys_user;
    +----+----------+------+--------+
    | id | name     | sex  | status |
    +----+----------+------+--------+
    |  8 | 0-true   | NULL |   NULL |
    |  9 | i-0-true | NULL |   NULL |
    | 10 | o-0-true | NULL |   NULL |
    | 11 | i-0-true | NULL |   NULL |
    | 16 | 0-true   | NULL |   NULL |
    +----+----------+------+--------+
    5 rows in set (0.00 sec)
    

      可以看出来,内部事务的失败不同事务下的插入操作。

    由如上的几个执行结果可以看出来,Required传播模式下的事务,会在已经存在事务的情况下加入已有的事务,按照现有事务的流程执行,没有事务的情况下,新建一个事务执行,其执行的结果对其他的事务不产生影响。

  • 相关阅读:
    shell查看内存
    shell 终端字符颜色
    PHP获取一年有几周以及每周开始日期和结束日期
    PHP 计算当前时间是这一年的第几周
    laravel orWhere
    进程与线程的一个简单解释
    go cap和len的区别
    go 总结常用函数
    go append 函数常见操作
    php 字符串常用函数
  • 原文地址:https://www.cnblogs.com/lyzw/p/9000564.html
Copyright © 2020-2023  润新知