• 隔离级别

  在 TransactionDefinition.java 接口中,定义了“四种”的隔离级别枚举:

/**
* 【Spring 独有】使用后端数据库默认的隔离级别
*
* MySQL 默认采用的 REPEATABLE_READ隔离级别
* Oracle 默认采用的 READ_COMMITTED隔离级别
*/
int ISOLATION_DEFAULT = -1; /**
* 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
*/
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED; /**
* 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
*/
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
/**
* 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
*/
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
/**
* 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
*
* 但是这将严重影响程序的性能。通常情况下也不会用到该级别。
*/
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;

  

  

  • 事务的传播级别

  事务的传播行为,指的是当前带有事务配置的方法,需要怎么处理事务;例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行;

  需要注意,事务的传播级别,并不是数据库事务规范中的名词,而是 Spring 自身所定义的。通过事务的传播级别,Spring 才知道如何处理事务,是创建一个新事务呢,还是继续使用当前的事务;

  在 TransactionDefinition.java 接口中,定义了三类七种传播级别:

// ========== 支持当前事务的情况 ========== 

/**
* 如果当前存在事务,则使用该事务。
* 如果当前没有事务,则创建一个新的事务。
*/
int PROPAGATION_REQUIRED = 0;
/**
* 如果当前存在事务,则使用该事务。
* 如果当前没有事务,则以非事务的方式继续运行。
*/
int PROPAGATION_SUPPORTS = 1;
/**
* 如果当前存在事务,则使用该事务。
* 如果当前没有事务,则抛出异常。
*/
int PROPAGATION_MANDATORY = 2; // ========== 不支持当前事务的情况 ========== /**
* 创建一个新的事务。
* 如果当前存在事务,则把当前事务挂起。
*/
int PROPAGATION_REQUIRES_NEW = 3;
/**
* 以非事务方式运行。
* 如果当前存在事务,则把当前事务挂起。
*/
int PROPAGATION_NOT_SUPPORTED = 4;
/**
* 以非事务方式运行。
* 如果当前存在事务,则抛出异常。
*/
int PROPAGATION_NEVER = 5; // ========== 其他情况 ========== /**
* 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行。
* 如果当前没有事务,则等价于 {@link TransactionDefinition#PROPAGATION_REQUIRED}
*/
int PROPAGATION_NESTED = 6;

  

  • @Transaction

  @Transaction 注解是Spring的tx模块提供的,使用AOP实现的事务控制,即底层为动态代理;

  @Transaction 可以作用于接口、接口方法、类以及类方法上;当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,也可以在方法级别使用该标注来覆盖类级别的定义;

  

  事务失效

  1.异常类型错误,默认是RuntimException才会回滚

  2.异常被catch后没有抛出,需要抛异常才能回滚

  3.是否发生自身调用的问题

  4.注解所在位置是否为public修饰

  5.数据源没有配置事务管理器

  6.不支持事务的引擎,如MyIsam

  下面是一个事务失效的例子

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper; @Transactional
@Override
public void parent() {
try {
this.child(); } catch (Exception e) {
log.error("插入异常", e);
} Order order = new Order();
order.setOrderNo("parent");
order.setStatus("0");
order.setTitle("parent");
order.setAmount("1000");
orderMapper.insert(order);
} @Transactional
@Override
public void child() { Order order = new Order();
order.setOrderNo("child");
order.setStatus("0");
order.setTitle("child");
order.setAmount("2000");
orderMapper.insert(order); throw new RuntimeException();
}
}

  当调用parent方法时,会调用child方法,但执行完成后插入的记录有两条,一条是parent的,一条是child的;

  

  这是因为上面的parent方法调用的child方法出现问题,@Transaction 是基于AOP的方式进行事务控制的(CglibAopProxy.java进行方法拦截,TransactionInterceptor.java进行代理对象调用执行方法),需要使用的是代理对象调用方法,上面的代码使用的还是this,即当前实例化对象,因此执行this.child(),方法不能被拦截增强;

  将上面的parent方法修改如下

    @Autowired
private ApplicationContext context; private OrderService orderService; @PostConstruct
public void init() {
orderService = context.getBean(OrderService.class);
} @Transactional
@Override
public void parent() {
try {
//获取代理对象,通过代理对象调用child()
orderService.child();        //获取代理对象
//OrderService orderService = (OrderService) AopContext.currentProxy();
//orderService.child();
} catch (Exception e) {
log.error("插入异常", e);
} Order order = new Order();
order.setOrderNo("parent");
order.setStatus("0");
order.setTitle("parent");
order.setAmount("1000");
orderMapper.insert(order);
}

  

   执行parent方法,当出现异常的时候,事务会进行回滚;

   如果想实现当调用parent方法时,调用child方法发生异常,只回滚child方法插入的数据,parent方法插入的数据不回滚,修改如下

@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void child() { Order order = new Order();
order.setOrderNo("child");
order.setStatus("0");
order.setTitle("child");
order.setAmount("2000");
orderMapper.insert(order); throw new RuntimeException();
}

    

 @Transactional(propagation = Propagation.REQUIRES_NEW)
 如果当前存在事务,则挂起事务并开启一个新事务执行,新事务执行完毕后,唤醒之前的挂起的事务,则继续执行;如果当前不存在事务,则新建一个事务;

Spring 事务失效的更多相关文章

  1. Spring事务失效的原因

    http://blog.csdn.net/paincupid/article/details/51822599 Spring事务失效的原因 5种大的原因 如使用mysql且引擎是MyISAM,则事务会 ...

  2. Spring事务失效的2种情况

    使用默认的事务处理方式 因为在java的设计中,它认为不继承RuntimeException的异常是”checkException”或普通异常,如IOException,这些异常在java语法中是要求 ...

  3. java面试记录二:spring加载流程、springmvc请求流程、spring事务失效、synchronized和volatile、JMM和JVM模型、二分查找的实现、垃圾收集器、控制台顺序打印ABC的三种线程实现

    注:部分答案引用网络文章 简答题 1.Spring项目启动后的加载流程 (1)使用spring框架的web项目,在tomcat下,是根据web.xml来启动的.web.xml中负责配置启动spring ...

  4. spring事务失效情况分析

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt113 <!--[if !supportLists]-->一.&l ...

  5. Spring事务失效的 8 大原因,这次可以吊打面试官了!

    今天再来一篇<吊打面试官>系列,这次真的要吊打了,哈哈!(看往期吊打系列请在后台回复:吊打,我会陆续更新--) 前几天栈长不是发了一篇文章,里面有一个关于事务失效的问题: 用 Spring ...

  6. Spring事务深入剖析--spring事务失效的原因

    之前我们讲的分布式事务的调用都是在一个service中的事务方法,去调用另外一个service中的业务方法, 如果在一个sevice中存在两个分布式事务方法,在一个seivice中两个事务方法相互嵌套 ...

  7. 就这?Spring 事务失效场景及解决方案

    小明:靓仔,我最近遇到了很邪门的事. 靓仔:哦?说来听听. 小明:上次看了你的文章<就这?一篇文章让你读懂 Spring 事务>,对事务有了详细的了解,但是在项目中还是遇到了问题,明明加了 ...

  8. 聊聊spring事务失效的12种场景,太坑了

    前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要么同时成功,要么同时失败),避免数据 ...

  9. spring事务失效的12种场景

    一 事务不生效 1.访问权限问题 java的访问权限主要有四种:private<default<protected<public. 把有某些事务方法,定义了错误的访问权限,就会导致事 ...

随机推荐

  1. 缓动公式整理(附:C#实现及WPF原版对比)

    前言 缓动在动画效果中应用非常广泛,在合适的时候使用一些缓动效果会使得效果更加符合人的直观感受,简单来说,会显得更加自然. WPF提供了11种缓动效果,涵盖了大部分的使用场景.不过如果需要在非WPF下 ...

  2. MyBatis学习(一)初识MyBatis

    一.MyBatis简介 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名 ...

  3. Python-函数式编程-map reduce filter lambda 三元表达式 闭包

    lambda 匿名函数,核心是作为算子,处理逻辑只有一行但具有函数的特性,核心用于函数式编程中 三元运算符 其实本质上是if分支的简化版,满足条件返回 if 前面的值,不满足条件返回 else后面的值 ...

  4. MyBatis 进阶,MyBatis-Plus!(基于 Springboot 演示)

    这一篇从一个入门的基本体验介绍,再到对于 CRUD 的一个详细介绍,在介绍过程中将涉及到的一些问题,例如逐渐策略,自动填充,乐观锁等内容说了一下,只选了一些重要的内容,还有一些没提及到,具体可以参考官 ...

  5. 084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字

    084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字 本文知识点:构造方法-this关键字 说明:因为时间紧 ...

  6. 达梦产品技术支持培训-day7-DM8数据库备份与还原-原理

    (本文部分内容摘自DM产品技术支持培训文档,如需要更详细的文档,请查询官方操作手册,谢谢) 1.DM8备份还原简介 1.1.基本概念 (1)表空间与数据文件 ▷ DM8表空间类型: ▷ SYSTEM ...

  7. 二进制搭建kubernetes-1.18.6单master集群

    master组件 kube-apiserver kubernetes API集群的同一入口,各组件协调者,以RESTful API提供接口服务,所有对象资源的增删改查和监听操作都交给APIserver ...

  8. 第五周:面向对象部分内容总结(5)---java设计规则

    面向对象设计原则 1.开闭原则 开闭原则理解: 简单说就是一个软件实体支持扩展,不支持修改.就是在不改变源码的基础上,扩展其它的功能. 其实笔者认为,开闭原则无非就是想表达这样一层意思:用抽象构建框架 ...

  9. CSP-S 2019 游记,以及AFO

    CSP-S:Day1 195 Day2 84 滚粗,AFO. Day0 和cyl神仙打了一会儿游戏,九点半教了cyl一下LCT,开始写板子题,写到十点半,睡觉. Day1 六点半起床.吃饭.赶赴考场, ...

  10. Nuxt|Vue仿探探/陌陌卡片式滑动|vue仿Tinder拖拽翻牌效果

    探探/Tinder是一个很火的陌生人社交App,趁着国庆假期闲暇时间倒腾了个Nuxt.js项目,项目中有个模块模仿探探滑动切换界面效果.支持左右拖拽滑动like和no like及滑动回弹效果. 一览效 ...