spring支持編程式事務管理和聲明式事務管理兩種方式。
編程式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於編程式事務管理,spring推薦使用TransactionTemplate。
聲明式事務管理創建在AOP之上的。其本質是對方法先後進行攔截,而後在目標方法開始以前建立或者加入一個事務,在執行完目標方法以後根據執行狀況提交或者回滾事務。聲明式事務最大的優勢就是不須要經過編程的方式管理事務,這樣就不須要在業務邏輯代碼中摻瑣事務管理的代碼,只需在配置文件中作相關的事務規則聲明(或經過基於@Transactional註解的方式),即可以將事務規則應用到業務邏輯中。html
顯然聲明式事務管理要優於編程式事務管理,這正是spring倡導的非侵入式的開發方式。聲明式事務管理使業務代碼不受污染,一個普通的POJO對象,只要加上註解就能夠得到徹底的事務支持。和編程式事務相比,聲明式事務惟一不足地方是,後者的最細粒度只能做用到方法級別,沒法作到像編程式事務那樣能夠做用到代碼塊級別。可是即使有這樣的需求,也存在不少變通的方法,好比,能夠將須要進行事務管理的代碼塊獨立爲方法等等。spring
聲明式事務管理也有兩種經常使用的方式,一種是基於tx和aop名字空間的xml配置文件,另外一種就是基於@Transactional註解。顯然基於註解的方式更簡單易用,更清爽。數據庫
事務有四個特性:ACID
原子性(Atomicity):事務是一個原子操做,由一系列動做組成。事務的原子性確保動做要麼所有完成,要麼徹底不起做用。
一致性(Consistency):一旦事務完成(無論成功仍是失敗),系統必須確保它所建模的業務處於一致的狀態,而不會是部分完成部分失敗。在現實中的數據不該該被破壞。
隔離性(Isolation):可能有許多事務會同時處理相同的數據,所以每一個事務都應該與其餘事務隔離開來,防止數據損壞。
持久性(Durability):一旦事務完成,不管發生什麼系統錯誤,它的結果都不該該受到影響,這樣就能從任何系統崩潰中恢復過來。一般狀況下,事務的結果被寫到持久化存儲器中。編程
事務的傳播行爲是指,若是在開始當前事務以前,一個事務上下文已經存在,此時有若干選項能夠指定一個事務性方法的執行行爲。在TransactionDefinition定義中包括了以下幾個表示傳播行爲的常量:併發
一、PROPAGATION_REQUIRED:若是當前存在事務,則加入該事務;若是當前沒有事務,則建立一個新的事務。這是默認值;ide
二、PROPAGATION_REQUIRES_NEW:建立一個新的事務,若是當前存在事務,則把當前事務掛起;優化
三、PROPAGATION_SUPPORTS:若是當前存在事務,則加入該事務;若是當前沒有事務,則以非事務的方式繼續運行;spa
四、PROPAGATION_NOT_SUPPORTED:以非事務方式運行,若是當前存在事務,則把當前事務掛起;code
五、PROPAGATION_NEVER:以非事務方式運行,若是當前存在事務,則拋出異常;orm
六、PROPAGATION_MANDATORY:若是當前存在事務,則加入該事務;若是當前沒有事務,則拋出異常;
七、PROPAGATION_NESTED:若是當前存在事務,則建立一個事務做爲當前事務的嵌套事務來運行;若是當前沒有事務,則該取值等價於PROPAGATION_REQUIRED。
詳解參考:Spring事務管理
先了解什麼是 髒數據, 髒讀, 不可重複讀, 幻讀?
髒讀: 一個事務正在對數據進行更新操做,可是更新還未提交,另外一個事務這時也來操做這組數據,而且讀取了前一個事務還未提交的數據,而前一個事務若是操做失敗進行了回滾,後一個事務讀取的就是錯誤數據,這樣就形成了髒讀。
不可重複讀: 一個事務屢次讀取同一數據,在該事務還未結束時,另外一個事務也對該數據進行了操做,並且在第一個事務兩次次讀取之間,第二個事務對數據進行了更新,那麼第一個事務先後兩次讀取到的數據是不一樣的,這樣就形成了不可重複讀。
幻覺讀: 幻讀與不可重複讀相似。它發生在一個事務讀取了幾行數據,接着另外一個併發事務插入了一些數據時。在隨後的查詢中,第一個事務就會發現多了一些本來不存在的記錄。
事務的隔離級別有如下5種:
一、default
默認的事務隔離級別
二、read_uncommitted
讀未提交,一個事務能夠操做另一個未提交的事務,不能避免髒讀,不可重複讀,幻讀,隔離級別最低,併發性 能最高
三、read_committed
讀已提交,一個事務不能夠操做另一個未提交的事務, 能防止髒讀,不能避免不可重複讀,幻讀。
四、repeatable_read
可以避免髒讀,不可重複讀,不能避免幻讀
五、serializable
隔離級別最高,消耗資源最低,代價最高,可以防止髒讀, 不可重複讀,幻讀。
/** * 1.添加事務註解 * 使用propagation 指定事務的傳播行爲,即當前的事務方法被另一個事務方法調用時如何使用事務。 * 默認取值爲REQUIRED,即便用調用方法的事務 * REQUIRES_NEW:使用本身的事務,調用的事務方法的事務被掛起。 * * 2.使用isolation 指定事務的隔離級別,最經常使用的取值爲READ_COMMITTED * 3.默認狀況下 Spring 的聲明式事務對全部的運行時異常進行回滾,也能夠經過對應的屬性進行設置。一般狀況下,默認值便可。 * 4.使用readOnly 指定事務是否爲只讀。 表示這個事務只讀取數據但不更新數據,這樣能夠幫助數據庫引擎優化事務。若真的是一個只讀取數據庫值得方法,應設置readOnly=true * 5.使用timeOut 指定強制回滾以前事務能夠佔用的時間。 */ @Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED, noRollbackFor={UserAccountException.class}, readOnly=true, timeout=3) @Override public void purchase(String username, String isbn) { //1.獲取書的單價 int price = bookShopDao.findBookPriceByIsbn(isbn); //2.更新書的庫存 bookShopDao.updateBookStock(isbn); //3.更新用戶餘額 bookShopDao.updateUserAccount(username, price); }