SpringBoot 2项目中,serviceA的方法中调用了serviceB的方法能触发事务吗

需求描述

在一个Spring Boot 2.x项目中,有一个需求是在serviceAmethod1方法中执行两个数据库操作,并在其中的某一步调用了serviceBmethod2,而method2也包含了数据库操作。

如果在这个过程中发生了异常,希望能够确保所有的数据库操作都能够回滚,以保持数据的一致性。该如何在代码中实现这个需求?


正文

先上结论:method1method2都加上 @Transactional注解

当在method1方法上添加@Transactional注解时,该方法及其内部的数据库操作将在一个事务中执行。如果在方法执行过程中抛出异常,Spring会回滚整个事务,包括method1方法中的数据库操作。

method1方法中调用serviceBmethod2时,如果method2方法也被标记为@Transactional,并且抛出了异常,整个事务将回滚,包括method1中的数据库操作和method2中的数据库操作。

事务的回滚是针对整个事务范围的,跨方法调用的情况同样适用。如果在任何被@Transactional标记的方法中抛出异常,Spring会回滚整个事务,确保所有数据库操作的一致性。

1、serviceAmethod1方法上添加@Transactional注解:

java 复制代码
@Service
public class ServiceA {

    @Autowired
    private ServiceB serviceB;

    @Transactional
    public void method1() {
        // 第一个数据库操作

        // 调用另一个Service的@Transactional方法
        serviceB.method2();

        // 第二个数据库操作

        // 如果发生异常,整个事务将回滚
    }
}

使用@Transactional注解的方法,如果在执行过程中发生异常,Spring会自动回滚整个事务。

2、serviceBmethod2方法上同样添加@Transactional注解:

java 复制代码
@Service
public class ServiceB {

    @Transactional
    public void method2() {
        // 第三个数据库操作

        // 如果发生异常,整个事务将回滚
    }
}

method2需要在方法上throws异常出去吗?

Spring默认会将未经检查的异常视为回滚原因,并触发事务回滚,无需在方法签名中声明。

如果抛出的是未经检查的异常(继承自RuntimeExceptionError),你不需要在method2的方法签名中使用throws声明。

如果发生的异常是受检查的异常(继承自Exception),你可能需要根据实际情况调整代码以处理这些异常。

示例代码:

java 复制代码
@Service
public class ServiceB {

    @Transactional(rollbackFor = XiaodouException.class)
    public void method2() throws YourCheckedException {
        // 操作数据库3

        // 抛出自定义,Spring会回滚事务
        throw new XiaodouException("Something went wrong in method2");
    }
}

额外注意事项

1、确保Spring Boot应用开启了事务管理

在项目启动类上添加@EnableTransactionManagement注解,以启用Spring的事务管理功能。

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement
public class XiaodouApplication {

    public static void main(String[] args) {
        SpringApplication.run(XiaodouApplication.class, args);
    }
}

2、数据库的配置需要在application.yml文件中添加,参考配置如下

yml 复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/xiaodoudatabase # 数据库密码
    username: root # 数据库登录用户名
    password: 123456 # 数据库密码
    driver-class-name: com.mysql.cj.jdbc.Driver # 数据库驱动
相关推荐
Leo July1 小时前
【Java】Spring Security 6.x 全解析:从基础认证到企业级权限架构
java·spring·架构
星火开发设计2 小时前
C++ 数组:一维数组的定义、遍历与常见操作
java·开发语言·数据结构·c++·学习·数组·知识
码道功成2 小时前
Pycham及IntelliJ Idea常用插件
java·ide·intellij-idea
消失的旧时光-19432 小时前
第四篇(实战): 订单表索引设计实战:从慢 SQL 到毫秒级
java·数据库·sql
それども2 小时前
@ModelAttribute vs @RequestBody
java
雨中飘荡的记忆3 小时前
深度详解Spring Context
java·spring
Tao____3 小时前
JAVA开源物联网平台
java·物联网·mqtt·开源·ruoyi
yqd6663 小时前
SpringSecurity的使用
java·spring
仙俊红3 小时前
Java Map 家族核心解析
java·开发语言
一嘴一个橘子4 小时前
springMvc 接收参数、cookie、header
java