SpringBoot中的手動提交事務(wù)
今天在工作中遇到了一個spring事務(wù)的問題:
在service方法內(nèi)需要通過線程去執(zhí)行添加用戶積分和用戶積分日志的情況,試了下通過@Transactional聲明式事務(wù)不起作用,只能使用手動事務(wù)去控制
因此寫了這篇博客,記錄一下這個情況
一、事務(wù)的重要性
相信在實(shí)際開發(fā)過程中,都有很深的了解了。
但是存在一個問題我們經(jīng)常在開發(fā)的時候一般情況下都是用的注解的方式來進(jìn)行事務(wù)的控制,說白了基于spring的7種事務(wù)控制方式來進(jìn)行事務(wù)的之間的協(xié)調(diào)。
二、spring的7中事務(wù)傳播行為
Propagation.REQUIRED | 代表當(dāng)前方法支持當(dāng)前的事務(wù),且與調(diào)用者處于同一事務(wù)上下文中,回滾統(tǒng)一回滾(如果當(dāng)前方法是被其他方法調(diào)用的時候,且調(diào)用者本身即有事務(wù)),如果沒有事務(wù),則自己新建事務(wù), |
---|---|
Propagation.SUPPORTS | 代表當(dāng)前方法支持當(dāng)前的事務(wù),且與調(diào)用者處于同一事務(wù)上下文中,回滾統(tǒng)一回滾(如果當(dāng)前方法是被其他方法調(diào)用的時候,且調(diào)用者本身即有事務(wù)),如果沒有事務(wù),則該方法在非事務(wù)的上下文中執(zhí)行 |
Propagation.MANDATORY | 代表當(dāng)前方法支持當(dāng)前的事務(wù),且與調(diào)用者處于同一事務(wù)上下文中,回滾統(tǒng)一回滾(如果當(dāng)前方法是被其他方法調(diào)用的時候,且調(diào)用者本身即有事務(wù)),如果沒有事務(wù),則拋出異常 |
Propagation.REQUIRES_NEW | 創(chuàng)建一個新的事務(wù)上下文,如果當(dāng)前方法的調(diào)用者已經(jīng)有了事務(wù),則掛起調(diào)用者的事務(wù),這兩個事務(wù)不處于同一上下文,如果各自發(fā)生異常,各自回滾 |
Propagation.NOT_SUPPORTED | 該方法以非事務(wù)的狀態(tài)執(zhí)行,如果調(diào)用該方法的調(diào)用者有事務(wù)則先掛起調(diào)用者的事務(wù) |
Propagation.NEVER | 該方法以非事務(wù)的狀態(tài)執(zhí)行,如果調(diào)用者存在事務(wù),則拋出異常 |
Propagation.NESTED | 如果當(dāng)前上下文中存在事務(wù),則以嵌套事務(wù)執(zhí)行該方法,也就說,這部分方法是外部方法的一部分,調(diào)用者回滾,則該方法回滾,但如果該方法自己發(fā)生異常,則自己回滾,不會影響外部事務(wù),如果不存在事務(wù),則與PROPAGATION_REQUIRED一樣 |
三、數(shù)據(jù)庫四大特性和MySQL事務(wù)的隔離級別
1)四大特性
a、原子性(Atomicity)
原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾。
b、 一致性(Consistency)
一致性是指事務(wù)必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另一個一致性狀態(tài),也就是說一個事務(wù)執(zhí)行之前和執(zhí)行之后都必須處于一致性狀態(tài)。
c、隔離性(Isolation)
隔離性是當(dāng)多個用戶并發(fā)訪問數(shù)據(jù)庫時,比如操作同一張表時,數(shù)據(jù)庫為每一個用戶開啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個并發(fā)事務(wù)之間要相互隔離。
d、 持久性(Durability)
持久性是指一個事務(wù)一旦被提交了,那么對數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會丟失提交事務(wù)的操作。
2)隔離級別
a、臟讀是指在一個事務(wù)處理過程里讀取了另一個未提交的事務(wù)中的數(shù)據(jù)。(讀取未提交的數(shù)據(jù))
b、不可重復(fù)讀是指在對于數(shù)據(jù)庫中的某個數(shù)據(jù),一個事務(wù)范圍內(nèi)多次查詢卻返回了不同的數(shù)據(jù)值,這是由于在查詢間隔,被另一個事務(wù)修改并提交了。(邊讀邊寫)
c、幻讀指兩個事務(wù)同時發(fā)生,兩個事務(wù)修改數(shù)據(jù),讀到的數(shù)據(jù)不是自己開始修改的數(shù)據(jù)?;米x和不可重復(fù)讀都是讀取了另一條已經(jīng)提交的事務(wù)(這點(diǎn)就臟讀不同),所不同的是不可重復(fù)讀查詢的都是同一個數(shù)據(jù)項(xiàng),而幻讀針對的是一批數(shù)據(jù)整體。(同時寫,同時讀)
3)數(shù)據(jù)庫事務(wù)級別
默認(rèn)使用Repeatable read級別,列表級別從下往上級別越低。
查看級別
select @@tx_isolation;
四、寫上面spring事務(wù)和數(shù)據(jù)庫事務(wù)隔離級別
主要的目的就是了解事務(wù)之間存在的傳遞關(guān)系,這樣在控制的時候,spring會通過事務(wù)與事務(wù)之間關(guān)系,來達(dá)到回滾或者提交的效果。
五、如果在沒有辦法使用注解的時候(比如多線程等)
就要使用手動的方式來做事務(wù)管理了,這也就是編程式的事務(wù)管理。
1)首先加入注解
這就是spring的jdbc框架中提供的事務(wù)管理方式
@Autowired private PlatformTransactionManager platformTransactionManager; @Autowired private TransactionDefinition transactionDefinition;
2)看一下源碼
(DataSourceTransactionManagerAutoConfiguration.class、TransactionTemplate.class)
@Bean @ConditionalOnMissingBean({PlatformTransactionManager.class}) public DataSourceTransactionManager transactionManager(DataSourceProperties properties) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource); if (this.transactionManagerCustomizers != null) { this.transactionManagerCustomizers.customize(transactionManager); } return transactionManager; }
備注:有興趣可以了解一下DataSourceTransactionManager的寫法和原理。
@Bean @ConditionalOnMissingBean public TransactionTemplate transactionTemplate() { return new TransactionTemplate(this.transactionManager); }
注意,這里的所有事務(wù)傳播方式包括處理,都需要自己手動去處理。
3)編寫方式
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition); platformTransactionManager.commit(transactionStatus); platformTransactionManager.rollback(transactionStatus);
說明:這里開發(fā)事務(wù)過后,返回一個事務(wù)狀態(tài),這個狀態(tài)記錄了東西,用來控制事務(wù)的管理,當(dāng)然,多個事務(wù)之間的控制需要人為控制。
4)編程式的事務(wù)控制經(jīng)量少用
因?yàn)榭刂瞥潭壬厦鎭碚fspring的方式還是來的更加不錯,編程式的方式,更多用于在需要事務(wù)的時候,沒有辦法加入事務(wù),才采取手動控制事務(wù)的方式。
使用示例 :
1 在service內(nèi)注入 這兩個bean @Autowired private PlatformTransactionManager platformTransactionManager; @Autowired private TransactionDefinition transactionDefinition; 2在 service方法內(nèi)創(chuàng)建TransactionStatus TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition); 通過 platformTransactionManager.commit(transactionStatus); 提交事務(wù) 通過 platformTransactionManager.rollback(transactionStatus); 回滾事務(wù) 示例代碼: @Autowired private PlatformTransactionManager platformTransactionManager; @Autowired private TransactionDefinition transactionDefinition; public void b(){ TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition); UserIntegralInfo info = new UserIntegralInfo(); info.setUserId(1L); info.setPoint(1); info.setOp(""); info.setCurrIntegral(1); integralMapper.insert(info); platformTransactionManager.commit(transactionStatus); throw new RuntimeException(); }
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
對java for 循環(huán)執(zhí)行順序的詳解
今天小編就為大家分享一篇對java for 循環(huán)執(zhí)行順序的詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06sentinel整合ribbon與fallback流程分步講解
這篇文章主要介紹了sentinel整合ribbon與fallback分步流程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08spring基礎(chǔ)概念A(yù)OP與動態(tài)代理理解
這篇文章主要為大家詳細(xì)介紹了spring基礎(chǔ)概念A(yù)OP與動態(tài)代理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-10-10java的Jackson框架實(shí)現(xiàn)輕易轉(zhuǎn)換JSON
本篇文章主要介紹了java的Jackson框架實(shí)現(xiàn)輕易轉(zhuǎn)換JSON,Jackson將Java對象轉(zhuǎn)換成json對象和xml文檔,同樣也可以將json、xml轉(zhuǎn)換成Java對象,有興趣的可以了解一下。2017-02-02SpringBoot使用WebSocket實(shí)現(xiàn)向前端推送消息功能
WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信——允許服務(wù)器主動發(fā)送信息給客戶端,本文給大家介紹了SpringBoot使用WebSocket實(shí)現(xiàn)向前端推送消息功能,需要的朋友可以參考下2024-05-05