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 # 数据库驱动
相关推荐
xmh-sxh-13144 分钟前
jdk各个版本介绍
java
XINGTECODE17 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
天天扭码23 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶23 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺28 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
小曲程序35 分钟前
vue3 封装request请求
java·前端·typescript·vue
凡人的AI工具箱1 小时前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
陈王卜1 小时前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、1 小时前
Spring Boot 注解
java·spring boot
先天牛马圣体1 小时前
如何提升大型AI模型的智能水平
后端