微信登录

事务管理 - 编程式事务 - 手动管理事务

Java - Web - Spring 《事务管理 - 编程式事务 - 手动管理事务》

在 Java Web 开发中,Spring 框架提供了强大的事务管理功能。事务管理是确保数据库操作的一致性和完整性的重要手段。Spring 的事务管理分为编程式事务和声明式事务,本文将重点介绍编程式事务,也就是手动管理事务。

什么是编程式事务?

编程式事务是指在代码中手动控制事务的开始、提交和回滚。这种方式虽然相对繁琐,但在一些特殊场景下,比如需要根据业务逻辑灵活控制事务边界时,编程式事务就非常有用。

编程式事务的实现步骤

在 Spring 中,编程式事务主要通过 TransactionTemplatePlatformTransactionManager 来实现。下面分别介绍这两种方式。

使用 TransactionTemplate

TransactionTemplate 是 Spring 提供的一个模板类,它简化了事务管理的代码。以下是一个使用 TransactionTemplate 的示例:

1. 配置 Spring 上下文

首先,需要在 Spring 配置文件中配置数据源、事务管理器和 TransactionTemplate。假设使用 Java 配置类:

  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  4. import org.springframework.jdbc.datasource.DriverManagerDataSource;
  5. import org.springframework.transaction.PlatformTransactionManager;
  6. import org.springframework.transaction.support.TransactionTemplate;
  7. import javax.sql.DataSource;
  8. @Configuration
  9. public class AppConfig {
  10. @Bean
  11. public DataSource dataSource() {
  12. DriverManagerDataSource dataSource = new DriverManagerDataSource();
  13. dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
  14. dataSource.setUrl("jdbc:mysql://localhost:3306/test");
  15. dataSource.setUsername("root");
  16. dataSource.setPassword("password");
  17. return dataSource;
  18. }
  19. @Bean
  20. public PlatformTransactionManager transactionManager(DataSource dataSource) {
  21. return new DataSourceTransactionManager(dataSource);
  22. }
  23. @Bean
  24. public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
  25. return new TransactionTemplate(transactionManager);
  26. }
  27. }

2. 编写业务服务类

在业务服务类中使用 TransactionTemplate 来管理事务:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.transaction.support.TransactionTemplate;
  5. @Service
  6. public class UserService {
  7. private final JdbcTemplate jdbcTemplate;
  8. private final TransactionTemplate transactionTemplate;
  9. @Autowired
  10. public UserService(JdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) {
  11. this.jdbcTemplate = jdbcTemplate;
  12. this.transactionTemplate = transactionTemplate;
  13. }
  14. public void transferMoney(int fromUserId, int toUserId, double amount) {
  15. transactionTemplate.execute(status -> {
  16. try {
  17. // 从转出用户账户扣除金额
  18. jdbcTemplate.update("UPDATE users SET balance = balance -? WHERE id =?", amount, fromUserId);
  19. // 模拟异常
  20. if (amount > 1000) {
  21. throw new RuntimeException("Transfer amount exceeds limit");
  22. }
  23. // 向转入用户账户添加金额
  24. jdbcTemplate.update("UPDATE users SET balance = balance +? WHERE id =?", amount, toUserId);
  25. return true;
  26. } catch (Exception e) {
  27. status.setRollbackOnly();
  28. return false;
  29. }
  30. });
  31. }
  32. }

3. 测试代码

  1. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  2. public class Main {
  3. public static void main(String[] args) {
  4. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  5. UserService userService = context.getBean(UserService.class);
  6. userService.transferMoney(1, 2, 500);
  7. System.out.println("Transaction completed successfully.");
  8. try {
  9. userService.transferMoney(1, 2, 1500);
  10. } catch (Exception e) {
  11. System.out.println("Transaction rolled back due to exception: " + e.getMessage());
  12. }
  13. context.close();
  14. }
  15. }

使用 PlatformTransactionManager

PlatformTransactionManager 是 Spring 事务管理的核心接口,通过它可以手动控制事务的各个阶段。以下是使用 PlatformTransactionManager 的示例:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.transaction.PlatformTransactionManager;
  5. import org.springframework.transaction.TransactionDefinition;
  6. import org.springframework.transaction.TransactionStatus;
  7. import org.springframework.transaction.support.DefaultTransactionDefinition;
  8. @Service
  9. public class UserServiceWithManager {
  10. private final JdbcTemplate jdbcTemplate;
  11. private final PlatformTransactionManager transactionManager;
  12. @Autowired
  13. public UserServiceWithManager(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {
  14. this.jdbcTemplate = jdbcTemplate;
  15. this.transactionManager = transactionManager;
  16. }
  17. public void transferMoney(int fromUserId, int toUserId, double amount) {
  18. TransactionDefinition def = new DefaultTransactionDefinition();
  19. TransactionStatus status = transactionManager.getTransaction(def);
  20. try {
  21. // 从转出用户账户扣除金额
  22. jdbcTemplate.update("UPDATE users SET balance = balance -? WHERE id =?", amount, fromUserId);
  23. // 模拟异常
  24. if (amount > 1000) {
  25. throw new RuntimeException("Transfer amount exceeds limit");
  26. }
  27. // 向转入用户账户添加金额
  28. jdbcTemplate.update("UPDATE users SET balance = balance +? WHERE id =?", amount, toUserId);
  29. transactionManager.commit(status);
  30. } catch (Exception e) {
  31. transactionManager.rollback(status);
  32. System.out.println("Transaction rolled back due to exception: " + e.getMessage());
  33. }
  34. }
  35. }

TransactionTemplatePlatformTransactionManager 的比较

比较项 TransactionTemplate PlatformTransactionManager
代码复杂度 较低,使用模板方法简化了事务管理 较高,需要手动管理事务状态
灵活性 相对较低,适合简单的事务场景 较高,可以更灵活地控制事务的各个阶段
异常处理 自动处理异常,可通过回调函数返回结果 需要手动捕获异常并处理事务回滚

总结

编程式事务虽然在代码编写上相对复杂,但在需要精确控制事务边界的场景下非常有用。TransactionTemplate 适合简单的事务管理,而 PlatformTransactionManager 则提供了更高的灵活性。在实际开发中,应根据具体业务需求选择合适的方式。通过本文的示例代码,你可以快速上手 Spring 的编程式事务管理。

事务管理 - 编程式事务 - 手动管理事务