Spring Boot 中事务的处理

在 Java 后端开发中,事务是一项重要的技术,用于确保数据库操作的一致性和可靠性。Spring Boot 提供了强大而简单的事务管理机制,使开发人员能够轻松地处理事务。

1. 什么是事务?

所谓事务,即要么都成功,要么不执行。

事务是对数据库操作的逻辑单位,它可以由一个或多个数据库操作组成。事务具有以下四个特性(ACID):

  • 原子性(Atomicity) :事务中的所有操作要么全部成功执行,要么全部回滚。如果任何一个操作失败,整个事务将被回滚到初始状态。
  • 一致性(Consistency) :事务必须使数据库从一个一致的状态转变到另一个一致的状态。在事务开始之前和结束之后,数据应该符合预定的规则。
  • 隔离性(Isolation) :事务之间应该相互隔离,每个事务的操作应该与其他事务的操作相互独立。这意味着每个事务应该感知不到其他事务的存在,并且不会相互干扰。
  • 持久性(Durability) :一旦事务提交成功,其结果应该永久保存在数据库中,即使系统故障也不会导致数据丢失。

2. 如何使用 Spring Boot 管理事务?

在 Spring Boot 中,可以使用 @Transactional 注解来管理事务。以下是一些关键点:

  • 在需要添加事务的方法上使用 @Transactional 注解。
  • 默认情况下,Spring Boot 使用基于注解的声明式事务管理,但也支持编程式事务管理。
  • 如果一个方法被标记为 @Transactional,当该方法被调用时,Spring Boot 将开启一个新的数据库事务。
  • 如果方法成功执行并完成,Spring Boot 将提交事务。否则,它将回滚事务并还原到最初状态。

下面是一个示例代码,演示了如何在 Spring Boot 中使用事务管理:

typescript 复制代码
@Service
public class UserService {
​
    @Autowired
    private UserRepository userRepository;
​
    @Transactional
    public void createUser(User user) {
        // 执行数据库操作
        userRepository.save(user);
    }
​
    @Transactional
    public void updateUser(User user) {
        // 执行数据库操作
        userRepository.save(user);
    }
​
    @Transactional
    public void deleteUser(long userId) {
        // 执行数据库操作
        userRepository.deleteById(userId);
    }
}

在上面的示例中,@Transactional 注解应用于三个方法,使它们成为事务性的方法。如果在执行期间出现异常,事务将回滚并抛出相应的异常。

需要注意的是:

@Transactional 注解只对 RuntimeException异常和其子类异常才有效。

如果使用不当会抛出 Transaction rolled back because it has been marked as rollback-only异常

场景如下:

  1. 有事务方法A调用了事务方法B
  2. 在事务B方法中抛出了 RuntimeException异常
  3. 事务方法A中使用 try/catch 捕获事务方法 B 中的异常,但是A方法只打印了错误日志,没有再抛出异常
  4. 现在事务方法 B 发生异常正常回滚
  5. 但是事务方法A执行完成之后认为一切正常,所以会走事务提交 commit 处理
  6. 整个执行下来,事务方法 B 执行的事务回滚,事务方法 A 执行的是事务提交
  7. Spring 事务做提交处理时发现,上次是回滚这次是提交,就抛回滚异常了

3. 配置事务属性

除了使用 @Transactional 注解外,我们还可以配置事务的其他属性。以下是一些常用的事务属性:

  • 传播行为(Propagation) :定义事务传播的行为,即当正在运行的方法已经在一个事务中时,新的方法调用是否应该加入同一事务。常用的传播行为包括 REQUIREDREQUIRES_NEWSUPPORTS 等。
  • 隔离级别(Isolation Level) :定义数据库事务隔离级别。常用的隔离级别包括 READ_COMMITTEDREAD_UNCOMMITTEDREPEATABLE_READSERIALIZABLE
  • 只读(Read Only) :指定事务是否只读。如果只涉及到读取操作而没有写入操作,可以将事务设置为只读以提高性能。
  • 超时(Timeout) :定义事务的超时时间。如果事务在指定的时间内未能完成,则会自动回滚。
  • 回滚规则(Rollback Rules) :定义哪些异常需要触发事务回滚。

通过在方法上使用 @Transactional 注解,可以方便地配置这些属性。例如:

typescript 复制代码
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, readOnly = true)
public void getUsers() {
    // 执行数据库查询操作
}

在上面的示例中,getUsers() 方法被配置为在一个现有事务中运行,隔离级别为 READ_COMMITTED,并且只执行读取操作。

结论

Spring Boot 提供了强大而简单的事务管理机制,使得处理事务变得更加容易。通过使用 @Transactional 注解和适当的配置,我们可以轻松地管理事务并确保数据库操作的一致性和可靠性。但是要注意使用的细节,使用不当会造成严重的后果。

相关推荐
许野平25 分钟前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
狂放不羁霸2 小时前
idea | 搭建 SpringBoot 项目之配置 Maven
spring boot·maven·intellij-idea
LunarCod2 小时前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
计算机学长felix3 小时前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友
码农派大星。3 小时前
Spring Boot 配置文件
java·spring boot·后端
江深竹静,一苇以航3 小时前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
杜杜的man3 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*3 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu4 小时前
Go语言结构体、方法与接口
开发语言·后端·golang