1. 程式人生 > 程式設計 >Spring宣告式事務@Transactional知識點分享

Spring宣告式事務@Transactional知識點分享

@Transactional註解支援9個屬性的設定,這裡只講解其中使用較多的三個屬性:readOnly、propagation、isolation。其中propagation屬性用來列舉事務的傳播行為,isolation用來設定事務隔離級別,readOnly進行讀寫事務控制。

@Service
@Transactional(readOnly = true)
public class AppTradeRec2Service extends BaseService {
 @Autowired
 private AppTradeRecDao appTradeRecDao;
 @Autowired
 private ConsInfoDao consInfoDao;
 
 @Transactional(readOnly = false)
 public void payCharge(TradeRec tradeRec) {
 User usr = UserUtils.getUser();
 ConsInfo cons = consInfoDao.getByUser(usr.getId());
 //修改交易記錄
 tradeRec.setPayBefore(cons.getAccountAmt());
 tradeRec.setPayAfter(cons.getAccountAmt() - tradeRec.getRcvAmt());
 tradeRec.setIsPay("99");
 appTradeRecDao.save(tradeRec);
 //修改賬戶餘額
 cons.setAccountAmt(cons.getAccountAmt() - tradeRec.getRcvAmt());
 consInfoDao.save(cons);
 }
}

一、readOnly讀寫事務控制

readOnly=true表明所註解的方法或類只是讀取資料。

readOnly=false表明所註解的方法或類是增加,刪除,修改資料。

二、isolation事務隔離級別

我們在使用事務過程中,通常會發生以下三種情況:

1、髒讀(dirty read):當一個事務讀取另一個事務尚未提交的修改時,產生髒讀。

2、不可重複讀(non-repeatable read):同一查詢在同一事務中多次進行,由於其他提交事務所做的修改或刪除,每次返回不同的結果集,此時發生非重複讀。

3、幻像讀(phantom read):同一查詢在同一事務中多次進行,由於其他提交事務所做的插入操作,每次返回不同的結果集,此時發生幻像讀。

針對上述三種情況,Spring提供了5種事務隔離級別予以解決:

1、DEFAULT預設級別

DEFAULT為資料來源(資料庫)的預設隔離級別,以目前常用的MySQL為例,預設的隔離級別通常為REPEATABLE_READ。

2、READ_UNCOMMITTED未授權讀取級別

這是最低的隔離級別,一個事務能讀取到別的事務未提交的更新資料,很不安全,可能出現丟失更新、髒讀、不可重複讀、幻讀。

3、READ_COMMITTED授權讀取級別

以操作同一行資料為前提,讀事務允許其他讀事務和寫事務,未提交的寫事務禁止其他讀事務和寫事務。此隔離級別可以防止更新丟失、髒讀,但不能防止不可重複讀、幻讀。此隔離級別可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。

4、REPEATABLE_READ可重複讀取級別

保證同一事務中先後執行的多次查詢將返回同一結果,不受其他事務影響。以操作同一行資料為前提,讀事務禁止其他寫事務,但允許其他讀事務,未提交的寫事務禁止其他讀事務和寫事務。此隔離級別可以防止更新丟失、髒讀、不可重複讀,但不能防止幻讀。

5、SERIALIZABLE序列化級別

所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾。提供嚴格的事務隔離,此隔離級別可以防止更新丟失、髒讀、不可重複讀、幻讀。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的資料不會被剛執行查詢操作的事務訪問到。

隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大。對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為Read Committed。它能夠避免更新丟失、髒讀,而且具有較好的併發效能。儘管它會導致不可重複讀、幻讀這些併發問題,在可能出現這類問題的個別場合,可以由應用程式採用悲觀鎖或樂觀鎖來控制。

三、Propagation事務傳播行為

Propagation屬性用來列舉事務的傳播行為。所謂事務傳播行為就是多個事務方法相互呼叫時,事務如何在這些方法間傳播。Spring支援7種事務傳播行為,預設為REQUIRED。

1、REQUIRED

REQUIRED是常用的事務傳播行為,如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。

2、SUPPORTS

SUPPORTS表示當前方法不需要事務上下文,但是如果存在當前事務的話,那麼這個方法會在這個事務中執行。

3、MANDATORY

MANDATORY表示該方法必須在事務中執行,如果當前事務不存在,則會丟擲一個異常。不會主動開啟一個事務。

4、REQUIRES_NEW

REQUIRES_NEW表示當前方法必須執行在它自己的事務中。一個新的事務將被啟動,如果存在當前事務,在該方法執行期間,當前事務會被掛起(如果一個事務已經存在,則先將這個存在的事務掛起)。如果使用JTATransactionManager的話,則需要訪問TransactionManager。

5、NOT_SUPPORTED

NOT_SUPPORTED表示該方法不應該執行在事務中,如果存在當前事務,在該方法執行期間,當前事務將被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager。

6、NEVER

NEVER表示當前方法不應該執行在事務上下文中,如果當前正有一個事務在執行,則會丟擲異常。

7、NESTED

NESTED表示如果當前已經存在一個事務,那麼該方法將會在巢狀事務中執行。巢狀的事務可以獨立於當前事務進行單獨地提交或回滾。如果當前事務不存在,那麼其行為與REQUIRED一樣。巢狀事務一個非常重要的概念就是內層事務依賴於外層事務。外層事務失敗時,會回滾內層事務所做的動作。而內層事務操作失敗並不會引起外層事務的回滾。

綜上所述,NESTED和REQUIRES_NEW非常相似,都是開啟一個屬於它自己的新事務。使用REQUIRES_NEW時,內層事務與外層事務就像兩個獨立的事務一樣,一旦內層事務進行了提交後,外層事務不能對其進行回滾。當內部事務開始執行時,外部事務將被掛起,內務事務結束時,外部事務將繼續執行。兩個事務互不影響,兩個事務不是一個真正的巢狀事務,同時它還需要JTA事務管理器的支援。

使用NESTED時,外層事務的回滾可以引起內層事務的回滾。而內層事務的異常並不會導致外層事務的回滾,它是一個真正的巢狀事務。巢狀事務開始執行時,它將取得一個 savepoint,如果這個巢狀事務失敗,將回滾到此savepoint。潛套事務是外部事務的一部分,只有外部事務結束後它才會被提交。

以上就是我們小編整理的全部內容,感謝大家的支援。