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 # 数据库驱动
相关推荐
风象南1 小时前
Token太贵?我用这个数据格式把上下文窗口扩大2倍
人工智能·后端
Victor3561 小时前
MongoDB(17)如何在MongoDB中创建集合?
后端
摸鱼的春哥1 小时前
春哥的Agent通关秘籍13:实现RAG查询
前端·javascript·后端
Victor3561 小时前
MongoDB(16)如何在MongoDB中创建数据库?
后端
勇哥java实战分享10 小时前
程序员的明天:AI 时代下的行业观察与个人思考
后端
掘金码甲哥12 小时前
超性感的轻量级openclaw平替,我来给你打call
后端
用户83562907805115 小时前
无需 Office:Python 批量转换 PPT 为图片
后端·python
啊哈灵机一动15 小时前
使用golang搭建一个nes 模拟器
后端
日月云棠16 小时前
各版本JDK对比:JDK 25 特性详解
java
间彧16 小时前
SpringBoot + ShardingSphere 读写分离实战指南
后端