上一篇实现的基于PlatformTransactionManater的编程式事务管理,是属于非常低级的封装,其实就是将原来的JDBC事务操作封装为一个接口而已,然后由具体的实现类来实现。
本篇通过TransactionTemplate类,实现了对固定流程代码的封装,只需要将视作原子性操作的几个数据库操作放入一个方法中处理即可实现事务。
修改配置类,在上一篇注册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),均会执行回滚操作,这个是比较符合我们期望的,在下一篇声明式事务管理里面,你会发现默认情况不是这样的,有点小坑啊。