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日

相关文章

  • 正确使用MySQL update语句

    当需要对MySQL数据库中的表进行修改时,我们可以使用update语句来更新数据。确定好需要更新记录的表名和需要更新的字段名之后,就可以按照以下步骤使用MySQL update语句进行操作。 步骤1:使用UPDATE语句确定需要更新的表 首先,需要使用UPDATE语句来确定需要更新的表,并指定该表的名称。 UPDATE tablename 步骤2:使用SET…

    database 2023年5月22日
    00
  • CentOS7.8安装mysql 8.0.20的教程详解

    CentOS7.8安装mysql 8.0.20的教程详解 简介 MySQL是一种常见的关系数据库管理系统,可以提供可靠、高性能的数据存储解决方案。CentOS是一个免费、开源的操作系统,广泛使用于服务器和桌面计算机。本文将介绍在CentOS 7.8上安装MySQL 8.0.20的详细步骤,以及如何配置MySQL服务器。 步骤 以下是在CentOS 7.8上安…

    database 2023年5月22日
    00
  • linux下mysql创建新的用户的方法

    下面是详细讲解“linux下mysql创建新的用户的方法”的完整攻略。首先我们需要知道,创建新用户需要在MySQL中以超级用户身份登录。登录MySQL的命令为: mysql -u root -p 其中,-u参数表示指定要登录的用户,这里指登录MySQL的超级用户root;-p参数表示指定登录密码,需要输入超级用户root的密码才能登录。在登录成功后,可以执行…

    database 2023年5月22日
    00
  • spring boot项目application.properties文件存放及使用介绍

    介绍 application.properties是SpringBoot项目中常用的一种配置文件,可以用来定义项目的各种属性值,其中包括:数据库链接信息、各种组件的属性以及其他一些自定义属性值等等。本文将对application.properties的存放位置、使用方法以及示例进行详细的介绍。 存放位置 在一个SpringBoot项目中,applicatio…

    database 2023年5月18日
    00
  • java servlet手机app访问接口(三)高德地图云存储及检索

    Java Servlet 手机 App 访问接口(三):高德地图云存储及检索 本教程将教你如何在你的 Java Servlet 手机 App 中使用高德地图云存储及检索服务。高德地图云提供了诸多方便的 API,能够管理和存储大规模的地图数据,支持高效查询、检索等等。我们将使用这些 API 来实现我们的手机 App。 准备工作 为了使用高德地图云的服务,我们需…

    database 2023年5月22日
    00
  • Linux中mysqldump命令实例详解

    Linux中mysqldump命令实例详解 简介 mysqldump是一个用于备份MySQL数据库的命令行工具,它能够将指定的数据库备份成可读的SQL文件,以便于备份、传输和重新部署。 mysqldump命令可用于导出整个数据库或者某个特定的表,并且您可以使用不同的方式来压缩和加密备份数据。 在本文中,我们将深入介绍mysqldump命令的使用方法和参数选项…

    database 2023年5月22日
    00
  • mysql动态游标学习(mysql存储过程游标)

    MySQL动态游标学习 在MySQL存储过程中,游标是用于遍历一个结果集并对每一行进行处理的机制。它可以将结果集的某个字段的值赋给一个变量,并在每一次处理时将游标移动到下一个记录上。MySQL存储过程提供了两种类型的游标: 静态游标和动态游标。本文主要介绍动态游标的使用。 动态游标 动态游标在定义时必须使用一个SELECT语句,这个语句的结果集就是动态游标的…

    database 2023年5月22日
    00
  • MySQL数据库安全设置与注意事项小结

    MySQL数据库安全设置与注意事项小结 MySQL是目前互联网上最为流行的开源数据库之一,它的安全性设置与注意事项非常重要,本文将为大家介绍MySQL数据库安全设置与注意事项,帮助大家保证数据的安全性。 1. 减少不必要的权限 MySQL中的用户权限可控制用户对数据库、表和列的访问级别。建议在生产环境中使用具有足够权限的专用用户。管理员不应向每个用户授予超出…

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