提起spring事务,就会让人联想起四大基本特征,五个隔离级别,七大传播特性。相信大多数人都知道这些东西,但是知道是一回事情,能用好真的是另一回事了。在使用Spring事务的时候,我曾遇到过几个比较严肃的问题,在这里我做一个自我总结。

问题一、 propagation.NESTED和propagation.REQUIRED_NEW有什么区别?

  当调用方不存在事务的时候,两者的效果是一致的。所以这里讨论问题的前提是调用方存在事务。PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行. 
另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务, 它是已经存在事务的一个真正的子事务. 潜套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. 
由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会被 commit, 这个规则同样适用于 roll back.

问题二、 @Transactional为什么会失效?

  1.调用方和被调用方属于同一个component,被调用方的 @Transacational 注解无效

  

package com.transacational;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by chenqimiao on 17/10/31.
 */
@Component
public class Service {

    public void test1(){
        test2();
    }

    @Transactional//此处的注解无效
    public void test2(){

    }
}

  

  2.被调用方不是一个public方法,被调用方的 @Transacational 注解无效

  

@Component
public class Service {

    @Resource
    private Service1 service1;

    public void test1(){
        test2();
        service1.test3();
    }

    @Transactional//1.此处的注解无效
    public void test2(){

    }
}
package com.transacational;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by chenqimiao on 17/10/31.
 */
@Component
public class Service1 {

    @Transactional//2.此处注解无效
    protected void test3(){

    }
}

  3.未开启事务开关,如:在springboot中,启动类未使用 @EnableTransactionManagement  

问题三、 如何理解@Transactional的超时时间

   timeout 是一个供开发者设置超时时间的属性。默认值-1,超时时间由具体的sql系统决定。

  

/**
 * Created by chenqimiao on 17/10/31.
 */
@Component
public class Service3 {

    @Resource
    private AdminInfoDoMapper adminInfoDoMapper;
    @Transactional(timeout = 4)//并不会超时
    public void test4(){

        adminInfoDoMapper.selectNameById(1);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

超时时间具体的定义:事务开始(在该方法第一句代码执行之前)到最后一个Statement执行完毕

所以象下面这样写,事务就会超时

@Component
public class Service3 {

    @Resource
    private AdminInfoDoMapper adminInfoDoMapper;
    @Transactional(timeout = 4)
    public void test4(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        adminInfoDoMapper.selectNameById(1);

    }
}

问题四、 @Transactional默认的回滚策略

默认情况下,只有当RuntimeException或其子类的异常被事务捕获之后,事务才会回滚,如果要让事务能够回滚所有异常,必须手动指定 @Transactional(rollbackFor=Exception.class) ,这样继承Exception的子类或者Exception本身都可以让事务回滚。

对Spring事务的一些误解的更多相关文章

  1. 【Spring】看了这篇Spring事务原理,我才知道我对Spring事务的误解有多深!

    写在前面 有很多小伙伴们留言说,冰河,你能不能写一篇关于Spring事务的文章呢?我:可以啊,安排上了!那还等什么呢?走起啊!! 事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有 ...

  2. Spring 事务管理高级应用难点剖析--转

    第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...

  3. Spring事务传播机制

    Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播,即协调已经有事务标识的方法之间的发生调用时的事务 ...

  4. Spring事务传播特性的浅析——事务方法嵌套调用的迷茫

    Spring事务传播机制回顾 Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务.结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷. 其实这 ...

  5. Spring 事务管理高级应用难点剖析: 第 1 部分

    Spring 的事务管理是被使用得最多的功能之一,虽然 Spring 事务管理已经帮助程序员将要做的事情减到了最小.但在实际开发中,如果使用不当,依然会造成数据连接泄漏等问题.本系列以实际应用中所碰到 ...

  6. spring事务传播行为讲解转载

    https://segmentfault.com/a/1190000013341344 前言 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为.事务传播行为是 ...

  7. Spring事务的传播属性

    前言 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为.事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为.这是Spring ...

  8. spring事务概念理解

    1.数据并发问题 脏读 A事务读取B事务尚未提交的更新数据,并在此数据的基础上操作.如果B事务回滚,则A事务读取的数据就是错误的.即读取了脏数据或者错误数据. 不可重复组 A事务先后读取了B事务提交[ ...

  9. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

随机推荐

  1. python实例编写(4)--js,滚动条,cookie,验证码,获取特定属性的元素,实现原理

    一.调用js 执行方法:execute_script(script,*args) 场景一:在页面上直接执行调用js 场景二:在定位的某个元素上执行调用js 如:掩藏文字(提示插件 tooltip设置淡 ...

  2. 基本的maven的命令行命令

    1.创建简单的maven 的web项目 mvn archetype:create 举例:mvn archetype:create -DgroupId=com.demo.app -DartifactId ...

  3. MyBatis的俩种事务管理器的类型

    JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置. 它依赖于从数据源得 到的连接来管理事务范围. MANAGED从来不回滚或提交一个连接而它会让 容器来管理事务的整个生命周期(比如 S ...

  4. StringBuffer的添加与删除功能

    StringBuffer的添加功能A* public StringBuffer append(String str): * 可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身 B* pu ...

  5. 为异常处理做准备,熟悉一下WinDbg工具

    为异常处理做准备,熟悉一下WinDbg工具 马上开始异常处理第二讲,但是在讲解之前,还有熟悉一下我们的WinDbg工具,当然你如果熟悉这个工具,那么就可以不用看了. 一丶熟悉WinDbg界面 刚开始打 ...

  6. Vue.js 服务端渲染业务入门实践

    作者:威威(沪江前端开发工程师) 本文原创,转载请注明作者及出处. 背景 最近, 产品同学一如往常笑嘻嘻的递来需求文档, 纵使内心万般拒绝, 身体倒是很诚实. 接过需求,好在需求不复杂, 简单构思 后 ...

  7. Quartz源码——QuartzSchedulerThread.run() 源码分析(三)

    QuartzSchedulerThread.run()是主要处理任务的方法!下面进行分析,方便自己查看! 我都是分析的jobStore 方式为jdbc的SimpleTrigger!RAM的方式类似分析 ...

  8. Python数据分析(二): Numpy技巧 (2/4)

    numpy.pandas.matplotlib(+seaborn)是python数据分析/机器学习的基本工具. numpy的内容特别丰富,我这里只能介绍一下比较常见的方法和属性.   昨天晚上发了第一 ...

  9. Gradient Boost 算法流程分析

    我们在很多Gradient Boost相关的论文及分析文章中都可以看到下面的公式: 但是,对这个公式的理解,我一直也是一知半解,最近,终于下决心对其进行了深入理解. 步骤1:可以看作优化目标的损失函数 ...

  10. Windows下MySQL5.6.21安装步骤

    01.把 mysql-advanced-5.6.17-winx64.zip 解压到自定义 D:\mysql-5.6.17-W64 或 D:\mysql-advanced-5.6.17-winx64 目 ...