Spring Boot的测试类中使用 @Transactional 注解

 更新时间:2026年05月28日 14:38:49   作者:yuejuejin  
本文主要介绍了Spring Boot的测试类中使用 @Transactional 注解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

我的数据库中有一列数据需要根据不同条件update为不同的状态值,我直接从ServiceImpl中复制了一个方法到Test中,修改完方法体中的几行代码后,执行Test,控制台打印了对应的update语句,但是数据库中该列的状态没有发生变化。原因就是复制过去的方法上带了 @Transactional 注解,我直接加了一个@Test就开始执行,导致事务回滚了。

现在来补一下相关知识。

在 Spring Boot 的测试类中使用 @Transactional 注解是一个常见且推荐的做法,但它的行为与你在生产代码中使用 @Transactional 有所不同,尤其是在执行修改 SQL(如 INSERT、UPDATE、DELETE)时。以下是详细解释:

1. 默认行为:事务回滚

当你在 Spring Boot 测试类(或测试方法)上使用 @Transactional 注解时,默认情况下,整个测试方法在一个事务中执行,并且在测试方法结束后,事务会自动回滚(rollback) ,而不是提交(commit)。

这意味着:

  • 你在测试中执行的修改 SQL(如 UPDATE user SET name = 'test' WHERE id = 1)会生效于当前事务内的数据库操作。
  • 其他数据库操作(如查询)能看到这些修改。
  • 但一旦测试方法执行完毕,Spring 会自动回滚该事务,所有对数据库的修改都不会永久保存到数据库中

2. 为什么这样设计?

这是为了保证测试的独立性可重复性

  • 每个测试运行后,数据库状态恢复到初始状态,不会影响其他测试。
  • 避免测试之间产生副作用。
  • 无需手动清理数据库数据。

3. 示例代码

@SpringBootTest
@Transactional
class UserServiceTest {
    @Autowired
    private UserService userService;
    @Autowired
    private UserRepository userRepository;
    @Test
    void testUpdateUser() {
        // 查询原始数据
        User user = userRepository.findById(1L).orElseThrow();
        String originalName = user.getName();
        // 执行修改 SQL(通过 Service 或直接 JPA)
        userService.updateUserName(1L, "NewName");
        // 在当前事务中可以查到修改
        User updatedUser = userRepository.findById(1L).orElseThrow();
        assertEquals("NewName", updatedUser.getName());
        // 测试结束,@Transactional 会导致事务回滚
        // 数据库中 id=1 的用户姓名仍为 originalName
    }
}

在这个例子中,updateUserName 方法执行的 SQL 修改在测试方法内部是可见的,但测试结束后,数据库不会真正更新。

4. 如何让修改真正提交?

如果你希望某个测试的修改真正提交到数据库(比如集成测试或性能测试),有以下几种方式:

方法一:移除@Transactional

@SpringBootTest
// 不加 @Transactional,每次修改都会提交
class IntegrationTest {
    @Test
    void testPersistData() {
        // 修改会真正写入数据库
    }
}

方法二:使用@Commit注解

@SpringBootTest
@Transactional
class UserServiceTest {

    @Test
    @Commit // 明确告诉 Spring 提交事务,而不是回滚
    void testUpdateAndCommit() {
        userService.updateUserName(1L, "CommittedName");
        // 测试结束后,修改会真正写入数据库
    }
}

到此这篇关于Spring Boot的测试类中使用 @Transactional 注解的文章就介绍到这了,更多相关Spring Boot使用@Transactional 注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实战小技巧之优雅的实现字符串拼接

    java实战小技巧之优雅的实现字符串拼接

    字符串拼接是我们在Java代码中比较经常要做的事情,就是把多个字符串拼接到一起,这篇文章主要给大家介绍了关于java实战小技巧之优雅的实现字符串拼接的相关资料,需要的朋友可以参考下
    2021-08-08
  • 浅谈java中Math.random()与java.util.random()的区别

    浅谈java中Math.random()与java.util.random()的区别

    下面小编就为大家带来一篇浅谈java中Math.random()与java.util.random()的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • Java设计模式之策略模式详细解析

    Java设计模式之策略模式详细解析

    这篇文章主要介绍了Java设计模式之策略模式详细解析,策略模式中,定义算法族,分别封装起来,让他们之间可以相互转化,此模式让算法的变化独立于使用算法的客户,需要的朋友可以参考下
    2023-11-11
  • java实现voctor按指定方式排序示例分享

    java实现voctor按指定方式排序示例分享

    这篇文章主要介绍了java实现voctor按指定方式排序示例,需要的朋友可以参考下
    2014-03-03
  • Java多线程并发之线程池任务请求拦截测试实例

    Java多线程并发之线程池任务请求拦截测试实例

    这篇文章主要介绍了Java多线程并发之线程池任务请求拦截测试实例,队列中永远没有线程被加入,即使线程池已满,也不会导致被加入排队队列,实现了只有线程池存在空闲线程的时候才会接受新任务的需求,需要的朋友可以参考下
    2023-12-12
  • Nacos注册中心的部署与用法示例详解

    Nacos注册中心的部署与用法示例详解

    注册中心是微服务架构中的纽带,类似于“通讯录”,它记录了服务和服务地址的映射关系,本文通过示例代码给大家介绍Nacos注册中心的部署与用法,感兴趣的朋友跟随小编一起看看吧
    2022-02-02
  • java 中Comparable与Comparator详解与比较

    java 中Comparable与Comparator详解与比较

    这篇文章主要介绍了java 中Comparable与Comparator详解与比较的相关资料,需要的朋友可以参考下
    2017-04-04
  • SpringBoot整合Drools的实现步骤

    SpringBoot整合Drools的实现步骤

    Drools是一个易于访问企业策略、易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快、效率高。业务分析师或审核人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行所需的业务规则。本文将讲述SpringBoot整合Drools的步骤
    2021-05-05
  • SpringAMQP的使用方式案例详解

    SpringAMQP的使用方式案例详解

    这篇文章主要介绍了SpringAMQP的使用方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • PowerMockito的基本使用解析

    PowerMockito的基本使用解析

    这篇文章主要介绍了PowerMockito的基本使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07

最新评论