SpringBoot事务管理-保姆级教程

admin 2025-06-28 23:37:39

Spring Boot 事务管理是确保数据一致性和完整性的重要机制。Spring 通过 @Transactional 注解简化了事务管理。以下是 Spring Boot 事务管理的详细教程。

1. 环境准备

确保你已经有一个 Spring Boot 项目。如果没有,可以通过 Spring Initializr 创建一个。

2. 添加依赖

Spring Boot 默认使用 Spring Data JPA 和 Hibernate 作为 ORM 框架。确保 pom.xml 中包含以下依赖:

org.springframework.boot

spring-boot-starter-data-jpa

org.springframework.boot

spring-boot-starter-web

com.h2database

h2

runtime

3. 配置数据源

在 application.properties 或 application.yml 中配置数据源和 H2 数据库(用于测试):

spring.datasource.url=jdbc:h2:mem:testdb

spring.datasource.driverClassName=org.h2.Driver

spring.datasource.username=sa

spring.datasource.password=password

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

spring.h2.console.enabled=true

4. 创建实体类

创建一个简单的实体类 User:

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

@Entity

public class User {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

private String name;

private String email;

// Getters and Setters

}

5. 创建 Repository 接口

创建一个 UserRepository 接口,继承 JpaRepository:

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository {

}

6. 创建 Service 层

在 Service 层中,使用 @Transactional 注解来管理事务:

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

@Service

public class UserService {

@Autowired

private UserRepository userRepository;

@Transactional

public void createUser(User user) {

userRepository.save(user);

}

@Transactional(readOnly = true)

public User getUserById(Long id) {

return userRepository.findById(id).orElse(null);

}

@Transactional

public void updateUser(User user) {

userRepository.save(user);

}

@Transactional

public void deleteUser(Long id) {

userRepository.deleteById(id);

}

}

7. 创建 Controller 层

创建一个简单的 REST Controller 来处理 HTTP 请求:

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

@RestController

@RequestMapping("/users")

public class UserController {

@Autowired

private UserService userService;

@PostMapping

public void createUser(@RequestBody User user) {

userService.createUser(user);

}

@GetMapping("/{id}")

public User getUserById(@PathVariable Long id) {

return userService.getUserById(id);

}

@PutMapping

public void updateUser(@RequestBody User user) {

userService.updateUser(user);

}

@DeleteMapping("/{id}")

public void deleteUser(@PathVariable Long id) {

userService.deleteUser(id);

}

}

8. 事务传播行为

Spring 提供了多种事务传播行为,可以通过 @Transactional 注解的 propagation 属性来指定:

REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则挂起当前事务。SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务。

示例:

@Transactional(propagation = Propagation.REQUIRES_NEW)

public void createUserWithNewTransaction(User user) {

userRepository.save(user);

}

9. 事务隔离级别

Spring 支持多种事务隔离级别,可以通过 @Transactional 注解的 isolation 属性来指定:

DEFAULT:使用底层数据库的默认隔离级别。READ_UNCOMMITTED:允许读取未提交的数据变更。READ_COMMITTED:只能读取已提交的数据变更。REPEATABLE_READ:确保在同一事务中多次读取同一数据时,结果一致。SERIALIZABLE:最高的隔离级别,确保事务串行执行。

示例:

@Transactional(isolation = Isolation.READ_COMMITTED)

public void updateUserWithIsolation(User user) {

userRepository.save(user);

}

10. 事务回滚

默认情况下,Spring 会在遇到 RuntimeException 或 Error 时回滚事务。你可以通过 @Transactional 注解的 rollbackFor 和 noRollbackFor 属性来指定哪些异常触发回滚:

@Transactional(rollbackFor = Exception.class)

public void createUserWithRollback(User user) throws Exception {

userRepository.save(user);

if (user.getName() == null) {

throw new Exception("User name cannot be null");

}

}

11. 测试事务

你可以编写单元测试来验证事务是否正常工作:

import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit.jupiter.SpringExtension;

@SpringBootTest

public class UserServiceTest {

@Autowired

private UserService userService;

@Test

public void testCreateUser() {

User user = new User();

user.setName("John Doe");

user.setEmail("john.doe@example.com");

userService.createUser(user);

// 验证用户是否成功创建

}

@Test

public void testUpdateUserWithException() {

assertThrows(RuntimeException.class, () -> {

userService.updateUser(1L, "new.email@example.com");

});

}

}

12. 事务的嵌套

Spring 支持嵌套事务,可以通过 Propagation.NESTED 来实现。嵌套事务允许在一个事务中启动另一个事务,内部事务可以独立提交或回滚,而外部事务可以控制整体事务的提交或回滚。

@Transactional(propagation = Propagation.REQUIRED)

public void outerMethod() {

// 外部事务逻辑

innerMethod();

// 外部事务逻辑

}

@Transactional(propagation = Propagation.NESTED)

public void innerMethod() {

// 内部事务逻辑

}

13. 事务的只读属性

如果某个方法只是读取数据而不修改数据,可以将事务标记为只读,以提高性能:

@Transactional(readOnly = true)

public User getUser(Long userId) {

return userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));

}

14. 事务的超时设置

你可以通过 @Transactional 注解的 timeout 属性来设置事务的超时时间(以秒为单位):

@Transactional(timeout = 10)

public void someMethod() {

// 业务逻辑

}

15. 事务失效的常见原因

15.1 方法非 public

@Transactional 只能用于 public 方法。

15.2 自调用问题

同一类中方法 A 调用方法 B(带 @Transactional),事务不生效。 解决:注入自身 Bean 或使用 AopContext.currentProxy()。

15.3 异常被捕获

@Transactional

public void update() {

try {

jdbcTemplate.update("..."); // SQL 异常

} catch (DataAccessException e) {

// 异常被吞,事务不会回滚!

}

}

15.4 数据库引擎不支持

如 MySQL 的 MyISAM 引擎不支持事务,需切换为 InnoDB。

16. 高级话题

分布式事务:Spring 的 JtaTransactionManager 或 Seata 框架。

编程式事务:使用 TransactionTemplate 手动控制。

@Autowired

private TransactionTemplate transactionTemplate;

public void doInTransaction() {

transactionTemplate.execute(status -> {

// 业务逻辑

return result;

});

}

17. 总结

特性配置方式常用场景传播行为propagation多方法嵌套调用隔离级别isolation高并发环境回滚规则rollbackFor/noRollbackFor自定义异常处理逻辑只读优化readOnly=true查询操作超时控制timeout防止长事务阻塞

通过 @Transactional 注解,Spring Boot 提供了简单而强大的事务管理机制。你可以通过配置传播行为、隔离级别和回滚规则来满足不同的业务需求。在实际开发中,合理使用事务管理可以确保数据的一致性和完整性。

18. 进一步学习

学习 Spring 的声明式事务管理和编程式事务管理。了解分布式事务和 Spring 的 @Transactional 在微服务架构中的应用。探索 Spring 的事务同步机制和事务事件监听器。