前面介紹的幾篇事務的博文,主要是利用@Transactional
註解的聲明式使用姿式,其好處在於使用簡單,侵入性低,可辨識性高(一看就知道使用了事務);然而缺點也比較明顯,不夠靈活,稍不注意,可能就由於姿式不對,致使事務不生效mysql
本文將介紹另一種事務的使用姿式,藉助TransactionTemplate
的編程式事務git
<!-- more -->github
本篇主要介紹的是jdbcTemplate
+transactionTemplate
來完成一個編程式事務的實例 demospring
建立一個 SpringBoot 項目,版本爲2.2.1.RELEASE
,使用 mysql 做爲目標數據庫,存儲引擎選擇Innodb
,事務隔離級別爲 RRsql
在項目pom.xml
文件中,加上spring-boot-starter-jdbc
,會注入一個DataSourceTransactionManager
的 bean,提供了事務支持數據庫
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
進入 spring 配置文件application.properties
,設置一下 db 相關的信息編程
## DataSource spring.datasource.url=jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false spring.datasource.username=root spring.datasource.password=
新建一個簡單的表結構,用於測試app
CREATE TABLE `money` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL DEFAULT '' COMMENT '用戶名', `money` int(26) NOT NULL DEFAULT '0' COMMENT '錢', `is_deleted` tinyint(1) NOT NULL DEFAULT '0', `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間', `update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間', PRIMARY KEY (`id`), KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=551 DEFAULT CHARSET=utf8mb4;
建立幾條數據,用於事務操做ide
@Service public class ManualDemo { @Autowired private TransactionTemplate transactionTemplate; @Autowired private JdbcTemplate jdbcTemplate; @PostConstruct public void init() { String sql = "replace into money (id, name, money) values (220, '初始化', 200)"; jdbcTemplate.execute(sql); } }
爲了演示事務的特性,咱們設計幾個簡單的 sql 操做,並拋出異常,引起回滾,以下
private boolean doUpdate(int id) throws Exception { if (this.updateName(id)) { this.query("after updateMoney name", id); if (this.updateMoney(id)) { return true; } } throw new Exception("參數異常"); } private boolean updateName(int id) { String sql = "update money set `name`='更新' where id=" + id; jdbcTemplate.execute(sql); return true; } public void query(String tag, int id) { String sql = "select * from money where id=" + id; Map map = jdbcTemplate.queryForMap(sql); System.out.println(tag + " >>>> " + map); } private boolean updateMoney(int id) { String sql = "update money set `money`= `money` + 10 where id=" + id; jdbcTemplate.execute(sql); return false; }
上面這一端邏輯,若是看了前面幾篇博文,會比較熟悉,區別在於 doUpdate 方法上面沒有添加@Transactional
註解,當下它的調用並不會在事務中執行
接下來咱們看一下編程式事務的核心寫法
public void testTransaction(int id) { transactionTemplate.execute(new TransactionCallback<Boolean>() { @Override public Boolean doInTransaction(TransactionStatus transactionStatus) { try { return doUpdate(id); } catch (Exception e) { transactionStatus.setRollbackOnly(); return false; } } }); }
如上,將方法的調用,封裝在transactionTemplate.execute
的調用中,經過設置transactionStatus.setRollbackOnly()
來標記回滾
經過前面幾篇博文的學習咱們知道實際使用時,事務的隔離級別,傳遞屬性也很重要,在編程式事務中,固然也是能夠設置的
// 設置隔離級別 transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT); // 設置傳播屬性 transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
最後寫一個測試代碼,驗證一下是否生效
@Component public class TransactionalSample { @Autowired private ManualDemo manualDemo; public void testManualCase() { System.out.println("======= 編程式事務 start ========== "); manualDemo.query("transaction before", 220); manualDemo.testTransaction(220); manualDemo.query("transaction end", 220); System.out.println("======= 編程式事務 end ========== "); } }
輸出結果以下,最終數據 big 沒有被修改
======= 編程式事務 start ========== transaction before >>>> {id=220, name=初始化, money=200, is_deleted=false, create_at=2020-02-03 13:52:39.0, update_at=2020-02-03 13:52:39.0} after updateMoney name >>>> {id=220, name=更新, money=200, is_deleted=false, create_at=2020-02-03 13:52:39.0, update_at=2020-02-03 13:52:39.0} transaction end >>>> {id=220, name=初始化, money=200, is_deleted=false, create_at=2020-02-03 13:52:39.0, update_at=2020-02-03 13:52:39.0} ======= 編程式事務 end ==========
系列博文
源碼
盡信書則不如,以上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激
下面一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛