Spring Boot 事务管理:声明式与编程式深度解析

Spring Boot 事务管理:声明式与编程式深度解析

各位看官,大家好!今天咱们聊聊Spring Boot里一个至关重要,却又容易让人摸不着头脑的家伙——事务管理。别怕,这玩意儿虽然听起来玄乎,但只要咱们抽丝剥茧,保证让它变得像隔壁老王家的烤串一样,香气扑鼻,容易上手!

想象一下,你正在开发一个银行转账系统。A账户要给B账户转100块钱。这个过程至少包含两个步骤:A账户扣钱,B账户加钱。如果在A账户扣钱成功后,B账户加钱失败了(比如网络崩了),那可就麻烦了!A账户的钱凭空消失,B账户也没收到钱,这简直是人间惨剧!

这就是事务要解决的问题。事务,简单来说,就是把一系列操作捆绑成一个原子操作。要么全部成功,要么全部失败,保证数据的一致性。

Spring Boot为我们提供了两种事务管理的方式:声明式事务和编程式事务。咱们先从声明式事务开始,因为它就像一个贴心的管家,帮你打理一切,省心省力。

声明式事务:优雅的管家

声明式事务,顾名思义,就是通过声明的方式来定义事务。我们只需要在方法或者类上添加注解,告诉Spring:“嘿,这个方法/类里面的操作需要在一个事务里执行!”Spring就会自动帮我们处理事务的开始、提交、回滚等操作。

1. 引入依赖

首先,确保你的项目中包含了Spring Boot的事务管理依赖。通常情况下,spring-boot-starter-data-jpa或者spring-boot-starter-jdbc已经包含了spring-tx,所以不需要额外引入。如果你的项目没有这些依赖,就需要手动添加:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

2. 开启事务支持

在你的Spring Boot应用主类上添加@EnableTransactionManagement注解,开启事务管理功能。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement
public class TransactionApplication {

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

3. 使用@Transactional注解

这是声明式事务的核心。@Transactional注解可以添加到类或者方法上。

  • 添加到类上: 表示该类中所有public方法都将在事务中执行。
  • 添加到方法上: 表示只有该方法在事务中执行。

示例:银行转账

假设我们有一个AccountService类,负责处理账户相关的业务逻辑。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class AccountService {

    @Autowired
    private AccountRepository accountRepository;

    @Transactional
    public void transfer(Long fromAccountId, Long toAccountId, Double amount) {
        Account fromAccount = accountRepository.findById(fromAccountId).orElseThrow(() -> new RuntimeException("From account not found"));
        Account toAccount = accountRepository.findById(toAccountId).orElseThrow(() -> new RuntimeException("To account not found"));

        fromAccount.setBalance(fromAccount.getBalance() - amount);
        toAccount.setBalance(toAccount.getBalance() + amount);

        accountRepository.save(fromAccount);
        accountRepository.save(toAccount);
    }
}

在这个例子中,transfer方法被@Transactional注解标记,这意味着该方法中的所有操作(包括查询账户、扣款、加款、保存账户)都将在一个事务中执行。如果其中任何一个操作失败,整个事务将会回滚,保证数据的一致性。

@Transactional注解的属性

@Transactional注解有很多属性,可以用来控制事务的行为。下面列出一些常用的属性:

属性名 描述 默认值
propagation 事务传播行为。定义了当一个方法被调用时,如何处理已存在的事务。 Propagation.REQUIRED
isolation 事务隔离级别。定义了多个事务并发执行时,一个事务对数据的修改,对其他事务的可见性。 Isolation.DEFAULT
timeout 事务超时时间。如果事务在指定时间内没有完成,则会自动回滚。单位为秒。 默认值由数据库决定
readOnly 是否为只读事务。如果是只读事务,则可以进行一些优化,例如禁用脏读检查。 false
rollbackFor 指定哪些异常需要回滚事务。默认情况下,只有RuntimeException及其子类和Error才会导致事务回滚。 默认回滚所有RuntimeExceptionError
noRollbackFor 指定哪些异常不需要回滚事务。
transactionManager 指定使用的事务管理器。如果你的应用中配置了多个事务管理器,你需要指定使用哪个事务管理器。 默认值由Spring决定

事务传播行为(propagation

事务传播行为是@Transactional注解中最复杂,但也最重要的属性之一。它定义了当一个被@Transactional注解标记的方法被另一个被@Transactional注解标记的方法调用时,事务应该如何处理。

Spring提供了以下几种事务传播行为:

传播行为 描述

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注