Spring Boot基礎教程15-使用SQL關係型數據庫-事務處理


、事務有四個特性:ACID 
原子性(Atomicity):事務是一個原子操作,由一系列動作組成。事務的原子性確保動作要麼全部完成,要麼完全不起作用。
一致性(Consistency):一旦事務完成(不管成功還是失敗),系統必須確保它所建模的業務處於一致的狀態,而不會是部分完成部分失敗。在現實中的數據不應該被破壞。
隔離性(Isolation):可能有許多事務會同時處理相同的數據,因此每個事務都應該與其他事務隔離開來,防止數據損壞。
持久性(Durability):一旦事務完成,無論發生什麼系統錯誤,它的結果都不應該受到影響,這樣就能從任何系統崩潰中恢復過來。通常情況下,事務的結果被寫到持久化存儲器中。
二、傳播行爲 
當事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中運行,也可能開啓一個新事務,並在自己的事務中運行。
Spring 定義了七種傳播行爲:
PROPAGATION_REQUIRED 表示當前方法必須運行在事務中。如果當前事務存在,方法將會在該事務中運行。否則,會啓動一個新的事務,Spring 默認使用
PROPAGATION_SUPPORTS 表示當前方法不需要事務上下文,但是如果存在當前事務的話,那麼該方法會在這個事務中運行
PROPAGATION_MANDATORY 表示該方法必須在事務中運行,如果當前事務不存在,則會拋出一個異常
PROPAGATION_REQUIRED_NEW 表示當前方法必須運行在它自己的事務中。一個新的事務將被啓動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用 JTATransactionManager 的話,則需要訪問 TransactionManager
PROPAGATION_NOT_SUPPORTED 表示該方法不應該運行在事務中。如果存在當前事務,在該方法運行期間,當前事務將掛起。如果使用 JTATransactionManager 的話,則需要訪問 TransactionManager

PROPAGATION_NEVER 表示當前方法不應該運行在事務上下文中。如果當前正有一個事務在運行,則會拋出異常
PROPAGATION_NESTED 表示如果當前已經存在一個事務,那麼該方法將會在嵌套事務中運行。嵌套的事務可以獨立於當前事務進行單獨地提交或回滾。如果當前事務不存在,那麼其行爲與
PROPAGATION_REQUIRED 一樣。注意各廠商對這種傳播行爲的支持是有所差異的。可以參考資源管理器的文檔來確認它們是否支持嵌套事務
三、隔離級別 
隔離級別定義了一個事務可能受其他併發事務影響的程度。
ISOLATION_DEFAULT 使用後端數據庫默認的隔離級別,Spring 默認使用,mysql 默認的隔離級別爲:
Repeatable Read(可重複讀) 
ISOLATION_READ_UNCOMMITTED 讀未提交,最低的隔離級別,允許讀取尚未提交的數據變更,可能會導致髒讀、幻讀或不可重複讀
ISOLATION_READ_COMMITTED 讀已提交,允許讀取併發事務已經提交的數據,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生
ISOLATION_REPEATABLE_READ 可重複讀,對同一字段的多次讀取結果都是一致的,除非數據是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生
ISOLATION_SERIALIZABLE 可串行化,最高的隔離級別,完全服從 ACID 的隔離級別,確保阻止髒讀、不可重複讀以及幻讀,也是最慢的事務隔離級別,因爲它通常是通過完全鎖定事務相關的數據庫表來實現的髒讀(Dirty reads)——髒讀發生在一個事務讀取了另一個事務改寫但尚未提交的數據時。如果改寫再稍後被回滾了,那麼第一個事務獲取的數據就是無效的。
不可重複讀(Nonrepeatable read)——不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但是每次都得到不同的數據時。這通常是因爲另一個併發事務在兩次查詢期間進行了更新。
幻讀(Phantom read)——幻讀與不可重複讀類似。它發生在一個事務(T1)讀取了幾行數據,接着另一個併發事務(T2)插入了一些數據時。在隨後的查詢中,第一個事務(T1)就會發現多了一些原本不存在的記錄。
四、屬性說明 @Transactional 
a、isolation:用於指定事務的隔離級別。默認爲底層事務的隔離級別。
b、noRollbackFor:指定遇到指定異常時強制不回滾事務。
c、noRollbackForClassName:指定遇到指定多個異常時強制不回滾事務。該屬性可以指定多個異常類名。
d、propagation:指定事務的傳播屬性。
e、readOnly:指定事務是否只讀。表示這個事務只讀取數據但不更新數據,這樣可以幫助數據庫引擎優化事務。若真的是一個只讀取的數據庫應設置 readOnly=true
f、rollbackFor:指定遇到指定異常時強制回滾事務。
g、rollbackForClassName:指定遇到指定多個異常時強制回滾事務。該屬性可以指定多個異常類名。
h、timeout:指定事務的超時時長。
注意: 
1.mysql 爲例,存儲引擎不能使用 MyISAM,應該使用 InnoDB 
實現代碼 
@Service
public class UserService {
@Autowired
private RoncooUserDao roncooUserDao;
@Autowired
private RoncooUserLogDao roncooUserLogDao;
/**
* 用戶註冊

* @return

*/
@Transactional
public String register(String name, String ip) {
// 1.添加用戶
RoncooUser roncooUser = new RoncooUser();
roncooUser.setName(name);
roncooUser.setCreateTime(new Date());
roncooUserDao.insert(roncooUser);
// 測試使用
boolean flag = true;
if (flag) {
throw new RuntimeException();
}
// 2.添加註冊日誌
RoncooUserLog roncooUserLog = new RoncooUserLog();
roncooUserLog.setUserName(name);
roncooUserLog.setUserIp(ip);
roncooUserLog.setCreateTime(new Date());
roncooUserLogDao.save(roncooUserLog);
return "success";
}
}
測試 
@Autowired
private UserService userService;
@Test
public void register() {
String result = userService.register("無境", "192.168.1.1");
System.out.println(result);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章