Spring @Transactional事务失效的原因分析

让我们来详细讲解 Spring @Transactional事务失效的原因分析。事务是应用程序中非常重要的概念,对于保证数据一致性具有至关重要的作用。Spring框架提供了@Transactional注解作为声明式事务管理的方式,可以极大的减轻我们对事务的控制。然而,有时候我们会发现@Transactional失效了,这时候我们需要对其原因进行分析。

一. 什么是 @Transactional?

@Transactional是Spring框架的注解,用于声明式的事务管理。在使用@Transactional注解的方法中,Spring会为其生成一个动态代理,这个代理会在方法开始调用时开启一个事务,在方法执行结束后,根据方法的执行情况决定是提交事务,还是回滚事务。

二. @Transactional 失效的原因

在实际的应用场景中,我们很容易发现@Transactional注解失效了的情况。下面我们将逐个解释事务失效的原因。

1. 对于只有一个@Transactional的方法内部调用了其他带有事务注解的方法

示例1

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void addUser(User user) {
        userDao.addUser(user);
        try {
            // 在当前方法内调用带有事务注解的方法
            // 由于事务的传播行为默认为REQUIRED,所以会继承当前的事务
            // 这个调用的方法执行了回滚操作,导致当前事务也回滚了
            addUserWithError(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Transactional
    public void addUserWithError(User user) {
        userDao.addUser(user);
        throw new RuntimeException("模拟数据重复添加异常");
    }

}

如果这个时候调用UserService.addUser方法,在执行addUserWithError方法时发生了异常,则由于事务传播行为的默认设置为Required,当前事务也会回滚。在addUser方法结束以后,针对于User的事务逻辑并没有生效,数据没有被插入进去。

示例2

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleService roleService;

    @Override
    public void addUser(User user, Role role) {
        userDao.addUser(user);
        // 在当前方法内调用另一个 Service 方法
        // 默认情况下,这个 Service 方法会在当前事务内进行操作
        roleService.addRole(role);
    }

}

@Service
@Transactional
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleDao roleDao;

    @Override
    public void addRole(Role role) {
        roleDao.addRole(role);
    }

}

因为在调用addRole方法时,当前事务并没有被关闭,所以实际上数据并没有被提交。因此,如果发现在@Transactional注解声明的方法内部调用了另一个带有事务注解的方法,务必保证被调用的方法不会回滚事务。

2. 对于一个类中的方法相互调用

假如一个类中有多个方法,在其中一个方法中使用了@Transactional注解,而另一个方法却直接调用了该方法。这时候事务就会失效。这是因为在这个类中,Spring通过生成代理类来管理事务,因此在同一个类中的方法中的@Transactional注解不会被代理类所拦截,从而导致事务失效。

示例

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    public void addUsers(List<User> users) {
        users.forEach(this::addUser);
    }

    public void addUser(User user) {
        userDao.addUser(user);
    }

}

如果在调用addUsers方法之前没有开启事务,则在addUser方法内插入数据库的数据并不会回滚。要解决这个问题,我们可以使用编程式事务的方式,在每个方法内部都手动开启和关闭事务。

三. 总结

在使用@Transactional注解时,务必要注意各个事务之间的传播行为。对于只有一个@Transactional的方法内部调用了其他带有事务注解的方法,务必保证被调用的方法不会回滚事务。对于一个类中的方法相互调用,需要注意事务的传播行为。如果遇到事务失效的问题,可以使用编程式事务的方式手动开启和关闭事务。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring @Transactional事务失效的原因分析 - Python技术站

(0)
上一篇 2023年5月21日
下一篇 2023年5月21日

相关文章

  • 人工智能自动sql优化工具–SQLTuning for SQL Server

    人工智能自动SQL优化工具–SQLTuning for SQL Server SQLTuning for SQL Server是一种人工智能自动化SQL优化工具。它能够根据数据库运行情况和配置,自动优化SQL语句,提高SQL的执行性能和稳定性。本文将详细介绍SQLTuning的使用方法和攻略,以及两个使用示例。 安装 SQLTuning for SQL S…

    database 2023年5月19日
    00
  • Linux(Unix)中误删除的文件恢复方法

    下面是针对“Linux(Unix)中误删除的文件恢复方法”的完整攻略。 1. 前言 在 Linux(或 Unix)系统上,误删文件是一个非常常见的错误操作,但好在 Linux 工具箱中有一些特殊的工具可以支持我们从磁盘中恢复这些文件。在本攻略中,我将介绍两种主要的误删除文件恢复方法,包括基于命令行的方法和基于应用程序的工具方法。 2. 使用命令行恢复文件 L…

    database 2023年5月22日
    00
  • redis 在 php 中的应用(Server[ 服务器] 篇)

    本文为我阅读了 redis参考手册 之后编写,注意 php_redis 和 redis-cli 的区别(主要是返回值类型和参数用法) 目录: Server(服务器) BGREWRITEAOF BGSAVE SAVE LASTSAVE DBSIZE SLAVEOF FLUSHALL FLUSHDB SLOWLOG INFO CONFIG GET CONFIG …

    Redis 2023年4月11日
    00
  • Django models文件模型变更错误解决

    当更新 Django 项目中的 models 文件后,在数据库中执行 python manage.py makemigrations 和 python manage.py migrate 命令时,可能会遇到“模型更改错误”的问题。该问题通常是由于修改 models.py 文件后忘记采取相应的步骤进行同步所导致的。以下是解决方案的完整攻略。 步骤 1:确定模型…

    database 2023年5月18日
    00
  • oracle 树查询 语句

    Oracle 树查询语句通常用于查询树形结构的数据。它们允许你从一张表中提取树形结构数据,甚至包括所有的父子关系和层级关系。下面是在 Oracle 数据库中使用树查询语句的完整攻略: 一、创建树形结构表 在任何数据库中,创建树形结构表的方法都类似。我们需要包含一个主键ID和一个父节点的ID列,还要包含一个约束,以确保每个节点都有一个父节点,除了根节点。 CR…

    database 2023年5月21日
    00
  • MySQL主键的设置与约束

    MySQL主键是用来唯一标识一个记录的列或者列的组合。主键必须是唯一的且不能为空,通常用来作为表中的索引,加速查询操作。 设置主键 在MySQL中,可以通过以下方式来设置主键: 1. 创建表时指定主键: 在创建表的时候,使用CREATE TABLE语句,并在指定列时加上PRIMARY KEY关键字来定义主键,例如: CREATE TABLE mytable …

    MySQL 2023年3月9日
    00
  • Redis远程连接Redis客户端的实现步骤

    当Redis服务器与客户端不在同一台计算机时,我们需要建立一个Redis远程连接,以允许客户端通过网络连接到Redis实例。下面是建立Redis远程连接的实现步骤: 步骤 1:启动 Redis 服务器 首先,你需要在远程服务器上安装并启动Redis服务。要安装Redis,请参考Redis官方文档。默认情况下,Redis服务监听端口为6379。您需要查看您的远…

    database 2023年5月22日
    00
  • Windows下MySQL详细安装过程及基本使用

    下面我将详细讲解一下“Windows下MySQL详细安装过程及基本使用”的完整攻略。 Windows下MySQL详细安装过程及基本使用攻略 1. 下载MySQL Installer 在安装MySQL之前,我们首先需要下载MySQL Installer。 我们可以前往MySQL官网,从官网的下载区域下载MySQL Installer。 2. 安装MySQL 下…

    database 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部