首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring 事务失效的 8 大场景

Spring 事务失效的 8 大场景

作者头像
Vincent-yuan
发布于 2021-08-10 02:33:30
发布于 2021-08-10 02:33:30
45900
代码可运行
举报
文章被收录于专栏:Vincent-yuanVincent-yuan
运行总次数:0
代码可运行

用 Spring 的 @Transactional 注解控制事务有哪些不生效的场景?

不知道小伙伴们有没有这样的经历,在自己开心的编写业务代码时候,突然某一个方法里的事务好像失效了。然后 debug 跟踪代码时发现,自己第一步的 insert 或者 update 的数据在语句执行完毕后,数据库中并没有立即出现更改或保存完的新数据。所以一度怀疑spring 的事务失效了。那么这篇文章就来总结一下,大家给大家造成 “spring事务失效”错觉的 几个常见场景,然后对症下药。

Let's GO!!! 以本人的经历中遇到的问题,大概分有以下几个场景:

  1. 数据库引擎是否支持事务(Mysql 的 MyIsam引擎不支持事务);
  2. 注解所在的类是否被加载为 Bean(是否被spring 管理);
  3. 注解所在的方法是否为 public 修饰的;
  4. 是否存在自身调用的问题;
  5. 所用数据源是否加载了事务管理器;
  6. @Transactional的扩展配置propagation是否正确。
  7. 异常被吃了
  8. 异常类型错误

下面展开分析每一个场景:

  • 数据库引擎不支持事务

这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。

根据 MySQL 的官方文档:

https://dev.mysql.com/doc/refman/5.5/en/storage-engine-setting.html

从 MySQL 5.5.5 开始的默认存储引擎是:InnoDB,之前默认的都是:MyISAM,所以这点要值得注意,底层引擎不支持事务再怎么搞都是白搭。

  • 没有被 Spring 管理

如下面例子所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// @Service
public class OrderServiceImpl implements OrderService {
 
    @Transactional
    public void updateOrder(Order order) {
        // update order
    }
 
}

如果此时把 @Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。

  • 方法不是 public 的

以下来自 Spring 官方文档:

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

大概意思就是 @Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。

  • 自身调用问题

来看两个示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//示例1
@Service
public class OrderServiceImpl implements OrderService {
 
    public void update(Order order) {
        updateOrder(order);
    }
 
    @Transactional
    public void updateOrder(Order order) {
        // update order
    }
 
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//示例2
@Service
public class OrderServiceImpl implements OrderService {
 
    @Transactional
    public void update(Order order) {
        updateOrder(order);
    }
 
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateOrder(Order order) {
        // update order
    }
 
}

示例1 中,update方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?

示例2 中,update方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?

这两个例子的答案是:都不管用! 因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。

这个的解决方案之一就是在的类中注入自己,用注入的对象再调用另外一个方法,这个不太优雅,另外一个可行的方案可以参考《Spring 如何在一个事务中开启另一个事务?》这篇文章。

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

如下代码所示,当前数据源若没有配置事务管理器,那也是白搭!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}
  • @Transactional的扩展配置不支持事务

Propagation.NOT_SUPPORTED: 表示不以事务运行,当前若存在事务则挂起。这表示不支持以事务的方式运行,所以即使事务生效也是白搭!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class OrderServiceImpl implements OrderService {
 
    @Transactional
    public void update(Order order) {
        updateOrder(order);
    }
 
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void updateOrder(Order order) {
        // update order
    }
 
}
  • 异常被吃了

这个也是出现比较多的场景:把异常吃了,然后又不抛出来,事务也不会回滚!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class OrderServiceImpl implements OrderService {
 
    @Transactional
    public void updateOrder(Order order) {
        try {
            // update order
        } catch {
 
        }
    }
 
}
  • 异常类型错误

接上面的例子,再抛出一个异常

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class OrderServiceImpl implements OrderService {
 
    @Transactional
    public void updateOrder(Order order) {
        try {
            // update order
        } catch {
            throw new Exception("更新错误");
        }
    }
 
}

这样事务也是不生效的,因为默认回滚的是:RuntimeException,如果你想触发其他异常的回滚,需要在注解上配置一下,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Transactional(rollbackFor = Exception.class)

这个配置仅限于 Throwable 异常类及其子类。

总结:本文总结了 8 种事务失效的场景,其实发生最多就是自身调用、异常被吃、异常抛出类型不对这 3 个了,像文章开头说的那样,本文不一定总结得全,只是总结常见的事务失效的场景

转自:

https://blog.csdn.net/Yang_yangyang/article/details/114359881

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring事务失效的 8 大原因,这次可以吊打面试官了!
这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。
AI码师
2020/11/19
4860
Spring事务失效的 8 大原因,这次可以吊打面试官了!
Spring事务失效的8种场景
这里以 MySQL为例,MyISAM引擎是不支持事务操作的,一般要支持事务都会使用InnoDB引擎,根据MySQL 的官方文档说明,从MySQL 5.5.5 开始的默认存储引擎是 InnoDB,之前默认的都是 MyISAM,所以这一点要值得注意,如果底层引擎不支持事务,那么再怎么设置也没有用。
每周聚焦
2024/11/27
2130
Spring事务失效的8种场景
面试专题:简述Spring事务失效原因?
Spring事务管理是一个非常重要的功能,但在实际操作中,可能会出现事务失效的情况。本文将简要介绍导致Spring事务失效的八大原因,帮助开发者在实际操作中避免这些问题,并且这个问题对于面试中,面试如果要深入面试,经常也会问,事务失效有哪些原因。
小明爱吃火锅
2023/12/20
3910
Spring事务在哪些情况下失效
因为事务是作用于数据库。例如使用MySQL且引擎是MyISAM,则事务会不起作用,因为MyISAM引擎本身不支持事务;如果改成InnoDB,则可以。
BUG弄潮儿
2020/06/15
1.1K0
面试必问|哪些场景下Spring的事务会失效?
在日常工作中,如果对Spring的事务管理功能使用不当,则会造成Spring事务不生效的问题。而针对Spring事务不生效的问题,也是在跳槽面试中被问的比较频繁的一个问题。
冰河
2021/12/20
3110
面试必问|哪些场景下Spring的事务会失效?
10 种 Spring 事务失效的常见场景,你知道几个?
Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事务 API,实现了一致的编程模型,而Spring的声明式事务功能更是提供了极其方便的事务配置方式,配合Spring Boot的自动配置,大多数Spring Boot项目只需要在方法上标记@Transactional注解,即可一键开启方法的事务性配置。
一行Java
2023/02/23
1.6K0
10 种 Spring 事务失效的常见场景,你知道几个?
每日一博 - 常见的Spring事务失效&事务不回滚案例集锦
在事务方法add中,直接调用事务方法updateStatus。 updateStatus方法拥有事务的能力是因为spring aop生成代理了对象,但是这种方法直接调用了this对象的方法,所以updateStatus方法不会生成事务。
小小工匠
2021/09/08
1.6K0
Spring事务失效的12种场景总结
上面代码中我们可以看到对于方法add的访问修饰符被定义成了private,这样会导致事务失效,原因是Spring 要求被代理的方法必须是 **public** 的。简单粗暴来看源码是怎么搞的。如下:
@派大星
2023/06/28
8.1K0
Spring事务失效的12种场景总结
Spring MVC系列-(6) 声明式事务
在进行数据操作事,通常会将多条SQL语句作为整体进行操作,这一条或者多条SQL语句就称为数据库事务。数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。如果事务失败,那么效果就和没有执行这些SQL一样,不会对数据库数据有任何改动。
码老思
2023/10/19
2130
Spring MVC系列-(6) 声明式事务
详细整理Spring事务失效的具体场景及解决方案
实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机制;好多小伙伴可能只是简单了解一下,遇到事务失效的情况,便会无从下手,溪源此篇文章给大家整理了一下常见Spring事务失效的场景,希望开发过程尽量避免踩坑,造成时间精力的浪费。 溪源按照最基本的使用方式以及常见失效场景优先级整理,先简单介绍一下具体失效场景:
沁溪源
2020/09/02
1.2K0
说吧,有没有被Spring事务坑过
新来的实习生找我吐槽,在开发过程中,经常遇到事务失效的问题,了不起实在看不下去了,整理了一份事务失效的N种情况,让他学习学习。
灬沙师弟
2023/05/18
3940
说吧,有没有被Spring事务坑过
Spring事务失效
在MySQL中,在MySQL 5.5.5版本之前默认的存储引擎为MyISAM,但是MyISAM引擎是不支持事务的,InnoDB才支持事务。可能有一些特殊情况导致使用MySQL 5.5.5之后版本的默认的存储引擎也为MyISAM,如果是这样,那么Spring事务便不会生效。可以在MySQL查询控制台中使用show engines;命令查看默认的存储引擎,比如:
Cikian.
2023/08/09
2400
Spring事务失效
Spring事务为什么会失效?
如果对AOP的实现不太熟悉的话可以看我之前的文章,或者到我网站www.javashitang.com上查看系列文章
Java识堂
2022/05/19
6330
Spring事务为什么会失效?
为什么 insert 配置 "SELECT LAST_INSERT_ID()" 返回个0呢?
我大抵是卷上瘾了,横竖都睡不着,坐起来身来打开Mac和外接显示器,这Bug没有由来,默然看着打印异常的屏幕,一个是我的,另外一个也是我的。
小傅哥
2022/07/18
1.1K0
Spring的事务那些场景会失效?
对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了。在某些业务场景下,如果同时有多张表的写入操作,为了保证操作的原子性(要么同时成功,要么同时失败)避免数据不一致的情况,我们一般都会使用spring事务。
猫头虎
2024/04/08
1320
Spring事务失效场景
如果@Transactional 没有特别指定,Spring 只会在遇到运行时异常RuntimeException或者error时进行回滚,而IOException等检查异常不会影响回滚。
科技新语
2022/12/22
4650
Spring事务失效场景
Spring声明式与编程式事务的区别,事务与非事务方法相互调用导致的事务不生效问题
序号 参数 含义 1 原子性(Atomicity) 事务是数据库的逻辑工作单位,它对数据库的修改要么全部执行,要么全部不执行。 2 一致性(Consistemcy) 事务前后,数据库的状态都满足所有的完整性约束。 3 隔离性(Isolation) 并发执行的事务是隔离的,一个不影响一个。通过设置数据库的隔离级别,可以达到不同的隔离效果 4 持久性(Durability) 在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
chenchenchen
2022/03/09
1.5K0
Spring声明式与编程式事务的区别,事务与非事务方法相互调用导致的事务不生效问题
@Transactional注解使用以及事务失效的场景
数据库事务,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
政采云前端团队
2023/09/28
2.4K0
@Transactional注解使用以及事务失效的场景
Spring事务详解
最近在项目组的业务技术分析会上,有同事遇到事务的失效的场景导致线上业务不可用。如果对Spring事务的@Transactional理解有限的话,确实很容易在开发中忽视一些细节问题,导致业务不可用的Bug。既然发生了问题,那么必然是要总结和反省的,然后我今天这里有时间总结一下各种事务失效的问题。
麋鹿大哥
2020/11/09
9610
Spring事务管理:应用实战案例和规则
有了Spring事务框架,我们再也不需要在与事务相关的方法中处理大量的try...catch...finaly代码。
后台技术汇
2024/10/21
2000
Spring事务管理:应用实战案例和规则
相关推荐
Spring事务失效的 8 大原因,这次可以吊打面试官了!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档