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

需求描述

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

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


正文

先上结论:method1和method2都加上 @Transactional注解

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

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

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

1、在serviceA的method1方法上添加@Transactional注解:

java 复制代码
@Service
public class ServiceA {

    @Autowired
    private ServiceB serviceB;

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

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

        // 第二个数据库操作

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

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

2、在serviceB的method2方法上同样添加@Transactional注解:

java 复制代码
@Service
public class ServiceB {

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

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

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

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

如果抛出的是未经检查的异常(继承自RuntimeException或Error),你不需要在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 # 数据库驱动
相关推荐
特立独行的猫A1 小时前
用仓颉语言 cj-tauri 框架,五分钟给娃做了个鸿蒙形近字游戏
java·后端·python
码事漫谈4 小时前
我花了一周时间,看AI公司怎么"管"AI,结果越看越后背发凉
后端
爱学习的程序媛7 小时前
Python常用框架梳理
开发语言·后端·python·ai·web·后端框架·python框架
GISer_Jing7 小时前
Agent核心内容
后端·ai·langchain
budingxiaomoli8 小时前
Spring统一功能处理
java·后端·spring
某鹏9 小时前
网关选型:Go、Java、Graal 谁都不能完胜
后端
用户0247836530979 小时前
从屎山到防线:14 行状态迁移表,给任务系统装上防瞎跳闸门
后端
CQU_JIAKE9 小时前
11.13[体系结构】指标,五级流水线,八级流水线,虚实地址思考
后端
Flynn Liang10 小时前
可观测性与成本治理:一次对话的 17 个观测点
java·langchain·可观测性·micrometer·langchain4j·token 成本·llm 监控
金銀銅鐵10 小时前
带您看懂字节码指令(三):同一行加法,为什么有四种指令
java·jvm