
在 Java Web 开发中,Spring 框架提供了强大的事务管理功能。事务管理是确保数据库操作的一致性和完整性的重要手段。Spring 的事务管理分为编程式事务和声明式事务,本文将重点介绍编程式事务,也就是手动管理事务。
编程式事务是指在代码中手动控制事务的开始、提交和回滚。这种方式虽然相对繁琐,但在一些特殊场景下,比如需要根据业务逻辑灵活控制事务边界时,编程式事务就非常有用。
在 Spring 中,编程式事务主要通过 TransactionTemplate 或 PlatformTransactionManager 来实现。下面分别介绍这两种方式。
TransactionTemplateTransactionTemplate 是 Spring 提供的一个模板类,它简化了事务管理的代码。以下是一个使用 TransactionTemplate 的示例:
首先,需要在 Spring 配置文件中配置数据源、事务管理器和 TransactionTemplate。假设使用 Java 配置类:
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.jdbc.datasource.DriverManagerDataSource;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.support.TransactionTemplate;import javax.sql.DataSource;@Configurationpublic class AppConfig {@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/test");dataSource.setUsername("root");dataSource.setPassword("password");return dataSource;}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Beanpublic TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {return new TransactionTemplate(transactionManager);}}
在业务服务类中使用 TransactionTemplate 来管理事务:
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import org.springframework.transaction.support.TransactionTemplate;@Servicepublic class UserService {private final JdbcTemplate jdbcTemplate;private final TransactionTemplate transactionTemplate;@Autowiredpublic UserService(JdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) {this.jdbcTemplate = jdbcTemplate;this.transactionTemplate = transactionTemplate;}public void transferMoney(int fromUserId, int toUserId, double amount) {transactionTemplate.execute(status -> {try {// 从转出用户账户扣除金额jdbcTemplate.update("UPDATE users SET balance = balance -? WHERE id =?", amount, fromUserId);// 模拟异常if (amount > 1000) {throw new RuntimeException("Transfer amount exceeds limit");}// 向转入用户账户添加金额jdbcTemplate.update("UPDATE users SET balance = balance +? WHERE id =?", amount, toUserId);return true;} catch (Exception e) {status.setRollbackOnly();return false;}});}}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Main {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);userService.transferMoney(1, 2, 500);System.out.println("Transaction completed successfully.");try {userService.transferMoney(1, 2, 1500);} catch (Exception e) {System.out.println("Transaction rolled back due to exception: " + e.getMessage());}context.close();}}
PlatformTransactionManagerPlatformTransactionManager 是 Spring 事务管理的核心接口,通过它可以手动控制事务的各个阶段。以下是使用 PlatformTransactionManager 的示例:
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.TransactionDefinition;import org.springframework.transaction.TransactionStatus;import org.springframework.transaction.support.DefaultTransactionDefinition;@Servicepublic class UserServiceWithManager {private final JdbcTemplate jdbcTemplate;private final PlatformTransactionManager transactionManager;@Autowiredpublic UserServiceWithManager(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {this.jdbcTemplate = jdbcTemplate;this.transactionManager = transactionManager;}public void transferMoney(int fromUserId, int toUserId, double amount) {TransactionDefinition def = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(def);try {// 从转出用户账户扣除金额jdbcTemplate.update("UPDATE users SET balance = balance -? WHERE id =?", amount, fromUserId);// 模拟异常if (amount > 1000) {throw new RuntimeException("Transfer amount exceeds limit");}// 向转入用户账户添加金额jdbcTemplate.update("UPDATE users SET balance = balance +? WHERE id =?", amount, toUserId);transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);System.out.println("Transaction rolled back due to exception: " + e.getMessage());}}}
TransactionTemplate 和 PlatformTransactionManager 的比较| 比较项 | TransactionTemplate | PlatformTransactionManager |
|---|---|---|
| 代码复杂度 | 较低,使用模板方法简化了事务管理 | 较高,需要手动管理事务状态 |
| 灵活性 | 相对较低,适合简单的事务场景 | 较高,可以更灵活地控制事务的各个阶段 |
| 异常处理 | 自动处理异常,可通过回调函数返回结果 | 需要手动捕获异常并处理事务回滚 |
编程式事务虽然在代码编写上相对复杂,但在需要精确控制事务边界的场景下非常有用。TransactionTemplate 适合简单的事务管理,而 PlatformTransactionManager 则提供了更高的灵活性。在实际开发中,应根据具体业务需求选择合适的方式。通过本文的示例代码,你可以快速上手 Spring 的编程式事务管理。