
在 Java Web 开发中,Spring 框架为我们提供了强大的事务管理功能。事务是一组不可分割的操作序列,要么全部成功执行,要么全部失败回滚。在数据库操作中,事务管理尤为重要,它可以保证数据的一致性和完整性。本文将详细介绍 Spring 中的事务管理,包括声明式事务和编程式事务,并通过示例代码进行演示。
Spring 支持多种事务隔离级别,常见的有:
| 隔离级别 | 描述 |
| —— | —— |
| ISOLATION_DEFAULT | 使用数据库默认的隔离级别。 |
| ISOLATION_READ_UNCOMMITTED | 允许读取未提交的数据,可能会出现脏读、不可重复读和幻读。 |
| ISOLATION_READ_COMMITTED | 只允许读取已提交的数据,避免了脏读,但可能会出现不可重复读和幻读。 |
| ISOLATION_REPEATABLE_READ | 确保在同一个事务中多次读取同一数据的结果是一致的,避免了脏读和不可重复读,但可能会出现幻读。 |
| ISOLATION_SERIALIZABLE | 最高的隔离级别,完全串行化执行事务,避免了脏读、不可重复读和幻读,但性能较低。 |
Spring 定义了 7 种事务传播行为,常见的有:
| 传播行为 | 描述 |
| —— | —— |
| PROPAGATION_REQUIRED | 如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务。 |
| PROPAGATION_SUPPORTS | 如果当前存在事务,则加入该事务;如果不存在事务,则以非事务方式执行。 |
| PROPAGATION_MANDATORY | 如果当前存在事务,则加入该事务;如果不存在事务,则抛出异常。 |
| PROPAGATION_REQUIRES_NEW | 无论当前是否存在事务,都创建一个新的事务,并挂起当前事务。 |
编程式事务管理需要在代码中显式地管理事务的开启、提交和回滚。以下是一个简单的示例:
import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.TransactionDefinition;import org.springframework.transaction.TransactionStatus;import org.springframework.transaction.support.DefaultTransactionDefinition;public class ProgrammaticTransactionExample {private JdbcTemplate jdbcTemplate;private PlatformTransactionManager transactionManager;public ProgrammaticTransactionExample(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {this.jdbcTemplate = jdbcTemplate;this.transactionManager = transactionManager;}public void transferMoney(int fromAccount, int toAccount, double amount) {TransactionDefinition def = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(def);try {// 从源账户扣除金额jdbcTemplate.update("UPDATE accounts SET balance = balance -? WHERE id =?", amount, fromAccount);// 模拟异常if (true) {throw new RuntimeException("Simulated exception");}// 向目标账户添加金额jdbcTemplate.update("UPDATE accounts SET balance = balance +? WHERE id =?", amount, toAccount);transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);throw e;}}}
声明式事务管理通过 AOP(面向切面编程)实现,只需要在配置文件或使用注解进行简单配置,就可以将事务管理逻辑与业务逻辑分离。以下是使用注解的示例:
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Servicepublic class DeclarativeTransactionExample {private JdbcTemplate jdbcTemplate;@Autowiredpublic DeclarativeTransactionExample(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Transactionalpublic void transferMoney(int fromAccount, int toAccount, double amount) {// 从源账户扣除金额jdbcTemplate.update("UPDATE accounts SET balance = balance -? WHERE id =?", amount, fromAccount);// 模拟异常if (true) {throw new RuntimeException("Simulated exception");}// 向目标账户添加金额jdbcTemplate.update("UPDATE accounts SET balance = balance +? WHERE id =?", amount, toAccount);}}
在 Spring 配置文件中,需要开启事务注解支持:
<tx:annotation-driven transaction-manager="transactionManager"/>
首先,需要在 pom.xml 中添加相关依赖:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.18</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency></dependencies>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test"/><property name="username" value="root"/><property name="password" value="password"/></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><tx:annotation-driven transaction-manager="transactionManager"/>
import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");DeclarativeTransactionExample example = context.getBean(DeclarativeTransactionExample.class);try {example.transferMoney(1, 2, 100.0);} catch (Exception e) {System.out.println("Transaction rolled back: " + e.getMessage());}}}
Spring 提供了强大的事务管理功能,编程式事务管理适合处理复杂的事务逻辑,而声明式事务管理则更简洁,将事务管理逻辑与业务逻辑分离,提高了代码的可维护性。在实际开发中,应根据具体需求选择合适的事务管理方式。同时,要合理设置事务的隔离级别和传播行为,以保证数据的一致性和完整性。通过本文的介绍和示例代码,相信你已经对 Spring 中的事务管理有了更深入的理解。