Spring 事务失效的7种场景, 事务失效后如何进行处理

文章目录

  • 简单说说spring事务失效的场景
    • Spring 事务失效的7种场景
        • 1.1、未启用[spring事务管理](https://so.csdn.net/so/search?q=spring事务管理&spm=1001.2101.3001.7020)功能
        • 1.2、方法不是public类型的
        • 1.3、数据源未配置事务管理器
        • 1.4、自身调用问题
        • 1.5、异常类型错误
        • 1.6、异常被吞了
        • 1.7、业务和spring事务代码必须在一个线程中
        • 2、如何快速定位事务相关bug?

简单说说spring事务失效的场景

Spring 事务失效的7种场景

  1. 未启用spring事务管理功能
  2. 方法不是public类型的
  3. 数据源未配置事务管理器
  4. 自身调用问题
  5. 异常类型错误
  6. 异常被吞了
  7. 业务和spring事务代码必须在一个线程中

1、数据库不支持事务

2、没有配置事务管理器

3、事务所在的方法没有被public修饰

4、异常被catch,没有抛出,事务会失效

5、异常类型错误,默认是runtimeException才会回滚的

​ 解决方案:加上@Transactional(rollbackFor = Exception.class)注解;这样Exception也会回滚

6、用final或者static关键字修饰的方法事务会失效

7、事务需要从外部调用,Spring 自调事务用会失效。即相同类里边,A 方法没有事务,B 方法有事务,A 方法调用 B 方法,则 B 方法的事务会失效,这点尤其要注意,因为代理模式只拦截通过代理传入的外部方法调用,所以自调用事务是不生效的。

1.1、未启用spring事务管理功能

@EnableTransactionManagement 注解用来启用spring事务自动管理事务的功能,这个注解千万不要忘记写了。

1.2、方法不是public类型的

@Transaction 可以用在类上、接口上、public方法上,如果将@Trasaction用在了非public方法上,事务将无效。

1.3、数据源未配置事务管理器

spring是通过事务管理器了来管理事务的,一定不要忘记配置事务管理器了,要注意为每个数据源配置一个事务管理器:

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}
1.4、自身调用问题

spring是通过aop的方式,对需要spring管理事务的bean生成了代理对象,然后通过代理对象拦截了目标方法的执行,在方法前后添加了事务的功能,所以必须通过代理对象调用目标方法的时候,事务才会起效。

看下面代码,大家思考一个问题:当外部直接调用m1的时候,m2方法的事务会生效么?

@Component
public class UserService {public void m1(){this.m2();}@Transactionalpublic void m2(){//执行db操作}
}

  显然不会生效,因为m1中通过this的方式调用了m2方法,而this并不是代理对象,this.m2()不会被事务拦截器,所以事务是无效的,如果外部直接调用通过UserService这个bean来调用m2方法,事务是有效的,上面代码可以做一下调整,如下,@1在UserService中注入了自己,此时m1中的m2事务是生效的.

@Component
public class UserService {@Autowired //@1private UserService userService;public void m1() {this.userService.m2();}@Transactionalpublic void m2() {//执行db操作}
}

重点:必须通过代理对象访问方法,事务才会生效。

1.5、异常类型错误

spring事务回滚的机制:对业务方法进行try catch,当捕获到有指定的异常时,spring自动对事务进行回滚,那么问题来了,哪些异常spring会回滚事务呢?

并不是任何异常情况下,spring都会回滚事务,默认情况下,RuntimeException和Error的情况下,spring事务才会回滚。

也可以自定义回滚的异常类型:

@Transactional(rollbackFor = {异常类型列表})
1.6、异常被吞了

当业务方法抛出异常,spring感知到异常的时候,才会做事务回滚的操作,若方法内部将异常给吞了,那么事务无法感知到异常了,事务就不会回滚了。

如下代码,事务操作2发生了异常,但是被捕获了,此时事务并不会被回滚

@Transactional
public void m1(){//事务操作1try{//事务操作2,内部抛出了异常}catch(Exception e){}
}
1.7、业务和spring事务代码必须在一个线程中

   spring事务实现中使用了ThreadLocal,ThreadLocal大家应该知道吧,可以实现同一个线程中数据共享,必须是同一个线程的时候,数据才可以共享,这就要求业务代码必须和spring事务的源码执行过程必须在一个线程中,才会受spring事务的控制,比如下面代码,方法内部的子线程内部执行的事务操作将不受m1方法上spring事务的控制,这个大家一定要注意

@Transactional
public void m1() {new Thread() {//一系列事务操作}.start();
}
2、如何快速定位事务相关bug?

2种方式

方式1:看日志

如果你使用了logback或者log4j来输出日志,可以修改一下日志级别为debug模式,可以看到事务的详细执行日志,帮助你定位错误

方式2:调试代码

如果你对源码比较了解,那么你会知道被spring管理事务的业务方法,执行的时候都会被TransactionInterceptor拦截器拦截,会进入到它的invoke方法中,咱们可以在invoke方法中设置一些断点,可以看到详细的执行过程,排错也就比较容易了。

整体上来说,还是需要你深入理解原理,原理了解了,写代码的时候本身就会避免很多坑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/165339.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《golang设计模式》第三部分·行为型模式-07-观察者模式(Observer)/发布者—订阅者模式

文章目录 1. 概念1.1 角色1.2 类图 2. 代码示例2.1 代码2.2 类图 1. 概念 观察者(Observer)指当目标对象状态发生变化后,对状态变化事件进行响应或处理的对象。 1.1 角色 Subject(抽象主题): 它可以有多…

微服务实战系列之Feign

前言 不知不觉,“微服务实战系列”已完成了六篇,每篇都聚焦一个主题,目的是便于各位盆友能够快速、全面地接收和消化。 博主从服务注册到服务监控,从服务路由到服务安全,从身份认证到加密技术均有涉猎。凡此均有关微服…

Java核心知识点整理大全10-笔记

往期快速传送门: Java核心知识点整理大全-笔记_希斯奎的博客-CSDN博客文章浏览阅读9w次,点赞7次,收藏7次。Java核心知识点整理大全https://blog.csdn.net/lzy302810/article/details/132202699?spm1001.2014.3001.5501 Java核心知识点整理…

【LeetCode刷题】--67.二进制求和

67.二进制求和 方法:模拟计算 class Solution {public String addBinary(String a, String b) {StringBuilder ans new StringBuilder();int carry 0;for(int ia.length()-1,jb.length()-1;i>0||j>0;i--,j--){int sum carry;sum i >0 ? a.charAt(i) …

web:[WUSTCTF2020]朴实无华

题目 点开页面显示如下 页面显示了一行报错:Cannot modify header information - headers already sent by (output started at /var/www/html/index.php:3) in /var/www/html/index.php on line 4 意思为不能修改报头信息-报头已经发送(输出开始于/var/www/html/i…

vue3 websocket连接 发送数据

先建一个websocket.js放在项目中,内容如下: var websock null; let rec; //断线重连后,延迟5秒重新创建WebSocket连接 rec用来存储延迟请求的代码 let isConnect false; //连接标识 避免重复连接 let checkMsg "heartbeat"; /…

MySQL与Redis如何保证数据的一致性

文章目录 MySQL与Redis如何保证数据的一致性?不好的方案1. 先写 MySQL,再写 Redis2. 先写 Redis,再写 MySQL3. 先删除 Redis,再写 MySQL 好的方案4. 先删除 Redis,再写 MySQL,再删除 Redis5. 先写 MySQL&am…

C# 数据库封装

最近有些地方用到c#,研究了一下,也有数据库方面的操作,那就继续封装,自己用起来好用一点。 数据库连接 using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using Sys…

Leetcode算法系列| 1. 两数之和(四种解法)

目录 1.题目2.题解解法一:暴力枚举解法二:哈希表解法解法三:双指针(有序状态)解法四:二分查找(有序状态) 1.题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数…

『RabbitMQ』入门指南(安装,配置,应用)

前言 RabbitMQ 是在 AMQP(Advanced Message Queuing Protocol) 协议标准基础上完整的,可复用的企业消息系统。它遵循 Mozilla Public License 开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,建立在 Erlang …

产品经理提问常用的ChatGPT通用提示词模板

如何评估产品市场的潜力和可行性? 如何定义和明确产品的目标用户和需求? 如何进行竞品分析和比较,制定产品的差异化策略? 如何设计产品的功能和特性,满足用户需求? 如何制定产品的定价策略和销售计划&a…

qml View3D使用介绍

在Qt Quick 3D中,View3D 是一个用于展示 3D 内容的 QML 类型。View3D 允许你将 3D 场景集成到 Qt Quick 2D 用户界面中,这意味着你可以在传统的 2D UI 元素(如按钮、文本和图像)与 3D 图形之间无缝地进行整合。 View3D 提供了一个视口,用于渲染 3D 场景。它可以包括多个 …

HTTPS攻击怎么防御?

HTTPS 简介 超文本传输安全协议( HTTPS )是一种通过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。 HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的…

批量将本地N个英文Html文档进行中文翻译-操作篇

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分…

QtCreator9.02不支持JDK11解决

最终效果 使用Android Studio 下载Android SDK Platform 31与Sources for Android 31 下载Android SDK Build Tools 31.0.0 下载NDK 25.1 ,23.1 ,21.3 重要: 下载Android SDK Command-Line Tools ,选择10.0或者9.0其中一个版本 其它版本不支持JDK11 ,本例选择10.0 下载CMak…

如何进行MySQL的主从复制(MySQL5.7)

背景:在一些Web服务器开发中,系统用户在进行数据访问时,基本都是直接操作数据库MySQL进行访问,而这种情况下,若只有一台MySQL服务器,可能会存在如下问题 数据的读和写的所有压力都会由一台数据库独…

浅析jdk8所包含的主要特性

至今Java 8仍然是许多开发者首选的JDK版本,Java 8的生态系统非常成熟,许多库和框架都已经适配了Java 8。迁移到新的Java版本可能需要重新评估和调整现有的依赖关系,这对于一些大型项目可能是一个挑战。那么Java 8有哪些特性让多数开发者钟爱呢…

西米支付:如何设计和构建游戏支付系统?

如何设计和构建游戏支付系统? 目前,游戏开发中最常见的支付方式包括微信支付、支付宝支付和苹果支付等。今天,我将与大家分享游戏支付系统的架构和设计。 游戏支付的主要业务流程是指游戏玩家在游戏中购买虚拟物品或服务所进行的支付过程。一…

ElasticSearch 7 SQL 详解

平时使用Elasticsearch的时候,会在Kibana中使用Query DSL来查询数据.每次要用到Query DSL时都基本忘光了,需要重新在回顾一遍,最近发现Elasticsearch已经支持SQL查询了(6.3版本以后),整理了下一些用法. 简介 Elasticsearch SQL是一个X-Pack组件,它允许针对Elasticsearch实时执…

ESP32之避障

ESP32之避障 图片 程序 int Led27;//定义LED 接口 int buttonpin4; //定义光遮断传感器接口 int val;//定义数字变量val void setup() { pinMode(Led,OUTPUT);//定义LED 为输出接口 pinMode(buttonpin,INPUT);//定义避障传感器为输出接口 } void loop() {Serial.begin(9600);…