Spring之路(39)–基于TransactionTemplate的编程式事务管理

简介: 本文目录1. 背景2. 代码实现

1. 背景

上一篇实现的基于PlatformTransactionManater的编程式事务管理,是属于非常低级的封装,其实就是将原来的JDBC事务操作封装为一个接口而已,然后由具体的实现类来实现。


本篇通过TransactionTemplate类,实现了对固定流程代码的封装,只需要将视作原子性操作的几个数据库操作放入一个方法中处理即可实现事务。


2. 代码实现

修改配置类,在上一篇注册PlatformTransactionManater类型bean的基础上,注册TransactionTemplate类型的bean,代码如下:

package org.maoge.templatetran;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import com.alibaba.druid.pool.DruidDataSource;
/**
* Spring配置类
*/
@Configuration
public class SpringConfig {
   /**
    * 定义数据源bean
    */
   @Bean
   public DataSource dataSource() {
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/myblog?useUnicode=true&characterEncoding=utf-8");
    dataSource.setUsername("root");
    dataSource.setPassword("Easy@0122");
    return dataSource;
   }
   /**
    * 定义事务管理bean
    */
   @Bean
   public PlatformTransactionManager transactionManager() {
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
    transactionManager.setDataSource(dataSource());// 注入dataSource
    return transactionManager;
   }
   /**
    * 定义TransactionTemplate类型的bean
    */
   @Bean
   public TransactionTemplate transactionTemplate() {
    TransactionTemplate transactionTemplate=new TransactionTemplate();
    transactionTemplate.setTransactionManager(transactionManager());//注入事务管理器
    return transactionTemplate;
   }
   /**
    * 配置namedParameterJdbcTemplate组件
    */
   @Bean
   public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
    NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(dataSource());// 注入dataSource
    return template;
   }
   /**
    * 为BlogDao注册bean
    */
   @Bean
   public BlogDao blogDao() {
    BlogDao blogDao = new BlogDao();
    blogDao.setNamedTemplate(namedParameterJdbcTemplate());// 注入namedParameterJdbcTemplate
    return blogDao;
   }
}

数据对象BlogDo和数据操作对象BlogDao没有任何变化:

package org.maoge.templatetran;
import java.util.HashMap;
import java.util.Map;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
/**
* @theme DAO--博客
* @author maoge
* @date 2020-01-29
*/
public class BlogDao {
   public NamedParameterJdbcTemplate getNamedTemplate() {
    return namedTemplate;
   }
   public void setNamedTemplate(NamedParameterJdbcTemplate namedTemplate) {
    this.namedTemplate = namedTemplate;
   }
   private NamedParameterJdbcTemplate namedTemplate;
   /**
    * 新增
    */
   public void insert(BlogDo blog) {
    Map<String, Object> map = new HashMap<>();
    map.put("author", blog.getAuthor());
    map.put("content", blog.getContent());
    map.put("title", blog.getTitle());
    // 注意使用:xxx占位
    namedTemplate.update("insert into blog(author,content,title)values(:author,:content,:title)", map);
   }
}
package org.maoge.templatetran;
/**
 * @theme 数据对象--博客
 * @author maoge
 * @date 2020-01-27
 */
public class BlogDo {
  private Long id;
  private String title;
  private String author;
  private String content;
  // 省略get get
}
测试验证,注意使用事务时,通过TransactionTemplate类的方法使用:
package org.maoge.templatetran;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class Main {
  public static void main(String[] args) {
    // 获取容器
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    // 容器中获取TransactionTemplate
    TransactionTemplate transactionTemplate = (TransactionTemplate) context.getBean("transactionTemplate");
    // 容器中获取数据库操作组件
    BlogDao blogDao = (BlogDao) context.getBean("blogDao");
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
      // 注意!该方法中的操作会实现事务
      @Override
      protected void doInTransactionWithoutResult(TransactionStatus arg0) {
        BlogDo blog = new BlogDo();
        blog.setContent("测试");
        blogDao.insert(blog);
        int a = 1 / 0;// 发生异常,导致事务回滚,所以并不会插入任何一行数据
        blogDao.insert(blog);
      }
    });
  }
}

需要注意的是,TransactionTemplate执行时,不论发生受检查的异常(Exception),还是不受检查的异常(RuntimeException),均会执行回滚操作,这个是比较符合我们期望的,在下一篇声明式事务管理里面,你会发现默认情况不是这样的,有点小坑啊。

相关文章
|
1月前
|
Java Spring
【编程笔记】在 Spring 项目中使用 RestTemplate 发送网络请求
【编程笔记】在 Spring 项目中使用 RestTemplate 发送网络请求
94 0
|
2月前
|
Java 数据库连接 应用服务中间件
Spring5源码(39)-Aop事物管理简介及编程式事物实现
Spring5源码(39)-Aop事物管理简介及编程式事物实现
24 0
|
3月前
|
Java 程序员 Maven
Spring AOP入门指南:轻松掌握面向切面编程的基础知识
Spring AOP入门指南:轻松掌握面向切面编程的基础知识
|
4月前
|
XML Java 程序员
Spring基础篇:注解编程
Spring基础篇:注解编程
|
1月前
|
Java 数据库 Spring
【spring(四)】Spring事务管理和@Transactional注解
【spring(四)】Spring事务管理和@Transactional注解
|
1天前
|
安全 Java Maven
[AIGC] Spring Boot中的切面编程和实例演示
[AIGC] Spring Boot中的切面编程和实例演示
|
13天前
|
Java 数据库 Spring
切面编程的艺术:Spring动态代理解析与实战
切面编程的艺术:Spring动态代理解析与实战
26 0
切面编程的艺术:Spring动态代理解析与实战
|
2月前
|
XML Java 数据库连接
无痛事务管理:Spring中的@Transactional和相关注解完全解析
无痛事务管理:Spring中的@Transactional和相关注解完全解析
179 0
|
3月前
|
XML 存储 Java
JAVAEE框架整合技术之Spring02-AOP面向切面编程技术
JAVAEE框架整合技术之Spring02-AOP面向切面编程技术
54 0
JAVAEE框架整合技术之Spring02-AOP面向切面编程技术
|
3月前
|
XML Java 数据格式
Spring 的AOP 简介,面向切面编程AOP
Spring 的AOP 简介,面向切面编程AOP
63 0