## TransactionTemplate - [TransactionTemplate](#transactiontemplate) - [一、基本信息](#一基本信息) - [二、基本描述](#二基本描述) - [三、主要功能](#三主要功能) - [四、最佳实践](#四最佳实践) - [五、源码分析](#五源码分析) ### 一、基本信息 ✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址 ** - [github](https://github.com/xuchengsheng/spring-reading) ### 二、基本描述 `TransactionTemplate` 是 Spring Framework 提供的工具类,用于在代码中以编程方式管理事务。它简化了事务的启动、提交/回滚以及异常处理,同时允许灵活配置事务属性,并提供了回调机制以执行特定操作。 ### 三、主要功能 1. **事务的启动和提交/回滚** + 允许我们以编程方式启动事务,并在需要时提交或回滚事务。这种方式使得我们可以在代码的特定部分明确定义事务的边界,而不必依赖于容器管理。 2. **异常处理** + 提供了对异常的处理机制,我们可以通过配置指定在发生异常时应该执行的操作,比如回滚事务。 3. **事务属性的灵活配置** + 我们可以使用 `TransactionTemplate` 配置各种事务属性,如隔离级别、传播行为等。这使得我们可以针对不同的场景灵活地配置事务行为。 4. **回调机制** + 允许我们定义回调接口,通过这些回调接口,我们可以在事务的不同阶段执行特定的操作。这为更复杂的事务场景提供了更大的灵活性。 ### 四、最佳实践 使用 `TransactionTemplate` 来管理事务。它首先创建了一个数据库连接,并通过 `DataSourceTransactionManager` 实例化了 `TransactionTemplate`。在 `TransactionTemplate` 的 `execute` 方法中,定义了一个事务回调接口,在该接口的 `doInTransaction` 方法中执行了数据库操作。通过这种方式,可以确保操作要么全部成功提交,要么全部回滚,从而保证数据的一致性和完整性。 ```java public class TransactionTemplateDemo { public static void main(String[] args) throws SQLException { // 数据库连接 URL,格式为 jdbc:数据库驱动名称://主机地址:端口号/数据库名称 String url = "jdbc:mysql://localhost:3306/spring-reading"; // 数据库用户名 String username = "root"; // 数据库密码 String password = "123456"; // 创建 SimpleDriverDataSource 对象,用于管理数据源 SimpleDriverDataSource dataSource = new SimpleDriverDataSource(new Driver(), url, username, password); // 创建 DataSourceTransactionManager 对象,用于管理事务 DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); // 创建 JdbcTemplate 对象,用于执行 SQL 语句 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // 创建事务模板 TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); Boolean insertSuccess = transactionTemplate.execute(new TransactionCallback() { @Override public Boolean doInTransaction(TransactionStatus status) { // 主键Id long id = System.currentTimeMillis(); // 分数 int score = new Random().nextInt(100); // 保存数据 int row = jdbcTemplate.update("insert into scores(id,score) values(?,?)", id, score); // 模拟异常,用于测试事务回滚 // int i = 1 / 0; // 我们也可以使用setRollbackOnly来回滚 // status.setRollbackOnly(); // 返回是否新增成功 return row >= 1; } }); System.out.println("新增scores表数据:" + insertSuccess); } } ``` 运行结果,数据库操作成功完成并成功提交了事务。 ```java 新增scores表数据:true ``` ### 五、源码分析 在`org.springframework.transaction.support.TransactionTemplate#execute`方法中,首先确保了 `PlatformTransactionManager` 已经设置,然后根据事务管理器的类型选择合适的执行方式。如果事务管理器是 `CallbackPreferringPlatformTransactionManager` 的实例,就会调用其 `execute` 方法来执行事务。否则,它将获取事务状态,执行事务回调操作,并在操作过程中处理可能的异常。最后,无论成功还是失败,都会提交事务。 ```java @Override @Nullable public T execute(TransactionCallback action) throws TransactionException { // 断言确保已设置PlatformTransactionManager Assert.state(this.transactionManager != null, "No PlatformTransactionManager set"); // 如果事务管理器是CallbackPreferringPlatformTransactionManager的实例 if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) { // 使用CallbackPreferringPlatformTransactionManager执行事务 return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action); } else { // 获取事务状态 TransactionStatus status = this.transactionManager.getTransaction(this); T result; try { // 执行事务回调操作 result = action.doInTransaction(status); } catch (RuntimeException | Error ex) { // 事务中的代码抛出应用程序异常 -> 回滚事务 rollbackOnException(status, ex); throw ex; } catch (Throwable ex) { // 事务中的代码抛出意外异常 -> 回滚事务 rollbackOnException(status, ex); throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception"); } // 提交事务 this.transactionManager.commit(status); return result; } } ``` 在`org.springframework.transaction.support.TransactionTemplate#rollbackOnException` 方法中,首先确保已设置了 `PlatformTransactionManager` ,然后记录调试日志以表示在应用异常时启动事务回滚。接着尝试执行事务回滚操作,如果发生回滚异常,则记录错误日志,并将原始异常初始化为回滚异常的应用程序异常。最后,如果发生运行时异常或错误,则将其重新抛出。 ```java /** * 在应用异常时执行回滚,正确处理回滚异常。 * @param status 表示事务的对象 * @param ex 抛出的应用程序异常或错误 * @throws TransactionException 如果发生回滚错误 */ private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException { // 断言确保已设置PlatformTransactionManager Assert.state(this.transactionManager != null, "No PlatformTransactionManager set"); // 打印调试日志,表示在应用异常时启动事务回滚 logger.debug("Initiating transaction rollback on application exception", ex); try { // 执行事务回滚 this.transactionManager.rollback(status); } catch (TransactionSystemException ex2) { // 打印错误日志,表示应用异常被回滚异常覆盖 logger.error("Application exception overridden by rollback exception", ex); // 初始化应用程序异常 ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException | Error ex2) { // 打印错误日志,表示应用异常被回滚异常覆盖 logger.error("Application exception overridden by rollback exception", ex); throw ex2; } } ```