jdbcTemplate事務管理

1、基於TransactionTemplate的編程式事務管理

Spring之路(39)–基於TransactionTemplate的編程式事務管理

  本篇通過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),均會執行回滾操作,這個是比較符合我們期望的,在下一篇聲明式事務管理裏面,你會發現默認情況不是這樣的,有點小坑啊。

 

  其他

  1)spring jdbcTemplate 事務,各種詭異,包你醍醐灌頂!

  2)3.16Spring對jdbcTemplate查詢語句的封裝和編程式事務及聲明式事務

  3)Spring學習筆記(五):JDBCTemplate+事務管理