在 Java Web 开发中,Spring 框架提供了强大的事务管理功能。事务管理是确保数据库操作的一致性和完整性的重要手段。Spring 的事务管理分为编程式事务和声明式事务,本文将重点介绍编程式事务,也就是手动管理事务。
编程式事务是指在代码中手动控制事务的开始、提交和回滚。这种方式虽然相对繁琐,但在一些特殊场景下,比如需要根据业务逻辑灵活控制事务边界时,编程式事务就非常有用。
在 Spring 中,编程式事务主要通过 TransactionTemplate
或 PlatformTransactionManager
来实现。下面分别介绍这两种方式。
TransactionTemplate
TransactionTemplate
是 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;
@Configuration
public class AppConfig {
@Bean
public 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;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public 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;
@Service
public class UserService {
private final JdbcTemplate jdbcTemplate;
private final TransactionTemplate transactionTemplate;
@Autowired
public 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();
}
}
PlatformTransactionManager
PlatformTransactionManager
是 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;
@Service
public class UserServiceWithManager {
private final JdbcTemplate jdbcTemplate;
private final PlatformTransactionManager transactionManager;
@Autowired
public 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 的编程式事务管理。