1. 介紹

在业务开发的许多场景中,我们会使用到通过事务去控制多个操作的一致性。比较多的就是通过声明式事务,即使用 @Transactional 注解修饰方法的形式。但在使用过程中,要足够了解事务失效的一些场景,提前规避在使用事务过程中出现事务失效的 bug 。下面就介绍下常见的事务失效的场景及原因分析。

2. 事务失效的场景及原因分析

场景一:数据库引擎不支持事务

以 Mysql 举例,在 5.5 版本之前,Mysql 默认的数据引擎都是 MyISAM 的,而 MyISAM 是不支持事务的;在 5.5 版本之后,默认的数据引擎是 InnoDB 的,它是支持事务的。而 Spring 对事务的管理实现又是基于数据库的,所以当数据库引擎不支持事务的时候,自然就不会有起作用的事务机制了。

如下:

mysql中创建表的时候是可以设置数据引擎的

场景二:事务所在类没有被 spring 管理

如下使用场景,当该类没有被 @Service 修饰时,是不会被 Spring 管理的,当然 @Transactional 事务注解就不能管理事务了。其实在使用过程中,当实现类没有使用 @Service 注解时,多数情况下在项目启动的时候会直接报错的。

// @Service
public class TestServiceImpl implements ITestService { @Override
@Transactional
public void test1() {
// test code
} }

场景三:注解作用的方法,是非 public 的

先看下来自 Spring 官方的解释:

<code>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 代理模式

场景四:属性 rollbackFor 设置错误

事务机制默认是当捕获到 RuntimeException 异常时,才会触发回滚。所以当抛出 RuntimeException 以外的异常时,而又想触发事务的回滚机制,就需要对 rollbackFor 属性做设置了。

例如:

当 throw 了 Exception 异常时,想要触发事务回滚,就要设置@Transactional(rollbackFor = Exception.class)

    @Transactional(rollbackFor = Exception.class)
public void test() {
// test code
if(1 == 1) {
throw new Exception("Exception 异常");
}
}

场景五:属性 propagation 设置错误

通过设置 @Transactional(propagation = Propagation.NOT_SUPPORTED) 可以配置 Spring 的事务传播机制的,当事务传播机制设置为不支持事务是,事务也是不会生效的。

例如:

当设置为 propagation = Propagation.NOT_SUPPORTED 时,表示不以事务运行,当前若存在事务则挂起。

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
public void test1() {
// test code }

场景六:调用同类中的方法

下面两种场景事务都是失效的,因为发生了直接的自我调用,没有经过代理。因为事务是基于代理实现的, 而这种情况会造成程序无法生成代理类,从而造成事务失效。

具体的解决方法,可以将该类通过注入的方式注入到自己中,再用注入的对象调用方法解决。

情况一:

@Service
public class TestServiceImpl implements ITestService { @Override
public void test1() {
// test code
test2();
} @Override
@Transactional
public void test2() {
// test code
}
}

情况二:

@Service
public class TestServiceImpl implements ITestService { @Override
@Transactional
public void test1() {
// test code
test2();
} @Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void test2() {
// test code
}
}

场景七:异常被捕获,无法触发事务回滚

事务机制的回滚,是 通过异常来触发事务回滚 的。在开发过程中,会出现异常被捕获处理了,而且没有再抛出新的异常,就会导致异常丢失,无法触发回滚。

不会触发回滚的情况:

    @Transactional
public void test1() {
// test code
try {
throw new RuntimeException();
} catch (RuntimeException e) {
// 不做处理,虽然有异常,但异常丢失,无法触发事务回滚
}
}

会触发回滚情况:( catch 异常后,再抛出)

    @Transactional
public void test1() {
// test code
try {
throw new RuntimeException();
} catch (RuntimeException e) {
// 不做处理,虽然有异常,但异常丢失,无法触发事务回滚
throw e;
}
}

@Transactional注解事务失效的几种场景及原因的更多相关文章

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

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

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

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

  3. spring 事务失效的几种场景

    以下场景是基于mysql数据库,InnoDB的存储引擎. 一.没有添加@Transactional注解 二.方法声明是private或者static 三.没有抛出异常而是try catch了异常 下面 ...

  4. 一口气说出 6种,@Transactional注解的失效场景

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 一口气说出 9种 分布式ID生成方式,面试官有点懵了 面试总被问 ...

  5. @Transactional注解的失效场景

    一口气说出 6种,@Transactional注解的失效场景 计算机java编程 发布时间: 20-03-1912:35优质科技领域创作者 引言 昨天公众号粉丝咨询了一个问题,说自己之前面试被问@Tr ...

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

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

  7. @transactional注解下失效

    这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚.后来终于找到了原因. 如果你也出现了这种情况,可以从下面开始排查. 一.特性 先来了解一下@Transactio ...

  8. spring@Transactional注解事务不回滚不起作用无效的问题处理

    这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚.后来终于找到了原因. 如果你也出现了这种情况,可以从下面开始排查. 一.特性先来了解一下@Transaction ...

  9. @Transactional注解事务不回滚不起作用无效

     写在前面 数据库Mysql8.0 添加@Transactional注解后事务并未起作用. 修改表的引擎后ok了.(详看下面转载内容) ================================ ...

  10. @Transactional注解事务不起作用

    @Transactional注解事务不起作用 问题:今天在项目中碰到一个事务问题,使用@Transactional注解事务,抛出异常不会滚. 解决一:https://blog.csdn.net/u01 ...

随机推荐

  1. CentOS6 配置阿里云 NTP 服务

    本文以Centos 6.5为例介绍如何修改Linux实例时区,以及开启和配置Linux NTP服务,保证实例本地时间精确同步. 前提条件 NTP服务的通信端口为UDP 123,设置NTP服务之前请确保 ...

  2. filebeat中增加其他参数用来区分不同的日志来源示例

    filebeat.yml配置文件参数 在source里加入了一个fields叫做"appach: true". filebeat.inputs: - type: log enabl ...

  3. 解决centos系统突然间网络不通的问题:Global IPv6 forwarding is disabled in configuration, but not currently disabled in kernel

    问题描述:公司里的一台centos 7.6主机,连接公司的路由器,里面设置的静态ip,之前用的好好的,但是有一次突然间ping不通了,之前是可以ping通的. 问题分析: 查看网络配置文件: TYPE ...

  4. 安装jumpserver 2.1.2版本遇到的坑

    官方文档地址:https://docs.jumpserver.org/zh/master/install/step_by_step/ Jumpserver 对外需要开放 80 和 2222 端口,如果 ...

  5. PAT (Basic Level) Practice 1031 查验身份证 分数 15

    一个合法的身份证号码由17位地区.日期编号和顺序编号加1位校验码组成.校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8, ...

  6. [CG从零开始] 6. 加载一个柴犬模型学习UV贴图

    在第 5 篇文章中,我们成功加载了 fbx 模型,并且做了 MVP 变换,将立方体按照透视投影渲染了出来.但是当时只是随机给顶点颜色,并且默认 fbx 文件里只有一个 mesh,这次我们来加载一个柴犬 ...

  7. 华为设备配置Stelnet命令

    配置SSH server:rsa local-key-pair create 生成本地RSA主机密钥对 display rsa local-key-pair public 查看本地密钥对中的公钥信息 ...

  8. 解决在vue中设置的height: 100%没有效果

    在新的页面设置height无效果的时候.需要改动App这个文件的heigth 解决办法.给app这个盒子设置高度.默认情况下为0 设置高度100%时,div的高度会等同于其父元素的高度.而上面中id为 ...

  9. 【.NET 6】RabbitMQ延迟消费指南

    背景 最近遇到一个比较特殊需求,需要修改一个的RabbitMQ消费者,以实现在消费某种特定的类型消息时,延迟1小时再处理,几个需要注意的点: 延迟是以小时为单位 不是所有消息都延迟消费,只延迟特定类型 ...

  10. 0025:2011年NOIp普及组真题——瑞士轮题解

    题目链接:https://www.luogu.com.cn/problem/P1309 如果是新手可能马上会想到sort排序,每比一次就排一次,但是这样的时间复杂度有点高,只有60分: 这是因为每次比 ...