Spring聲明式事務的使用:由@Transactional進行標註,可使用在類和方法上。當標註在類上,類下面全部公共非靜態的方法都將啓用事務功能。接下來,運行事務註解標註的方法,Spring的事務攔截器就會同時使用事務管理的方法開啓事務,而後將代碼織入Spring數據庫事務的流程中,若是發生異常,就會回滾,若是不發生異常,那麼就會提交事務。spring
spring事務流程圖(本身瞎畫的):sql
1.@Transactional源碼分析: timeout是事務能夠存在的時間戳.(單位爲秒) Value和transactionManager屬性是配置的一個Spring事務管理器. readOnly屬性定義事務是否只讀. rollbackFor,rollbackForClassName,noRollbackFor和noRollbackForClassName都是指定異常.發生什麼異常回滾事務. propagation傳播行爲. isolation隔離級別 2.隔離級別: 關於隔離級別,先說一下數據庫事務的4個基本特徵,也就是ACID,也算是老話長談了, 原子性:(事務的操做是一個總體,要麼所有成功,要麼所有失敗,不會出現部分紅功,部分失敗.), 一致性:(事務在完成的時候,必須全部的數據都保持一致的狀態.), 隔離性:(不一樣事務操做的數據,互相不影響), 持久性:(事務執行事後,數據會存儲到數據庫中) 隔離級別解決的事情,舉個例子說明: 2.1.一個商品初始化爲2,事務一扣減庫存1,庫存爲1,事務2扣減庫存,讀取到事務1爲提交的庫存數據,扣減庫存1,提交事務,庫存保存爲0,事務一回滾事務,庫存結果爲0,結果錯誤. 未提交讀(read uncommitted)最低的隔離級別,容許一個事務度去另外一個事務沒有提交的數據. 2.2.讀寫提交(read committed)隔離級別,是指定一個事務只能讀取另一個事務已經提交的數據,不能讀取未提交的數據.有效的解決了2.1.髒讀的問題. 可是仍舊會出現下列問題: 不可重讀場景:商品庫存初始化爲1,事務一讀取庫存1,扣減庫存,未提交,事務2讀取庫存1,認爲能夠扣減,此時事務一提交,庫存變爲0,事務2扣減庫存失敗,庫存爲0,沒法扣減. 可重複讀:就是克服讀寫提交中出現的不可重複讀的狀況,由於在讀寫提交的時候,確實會出現一些值的變化. 簡單點說,就是庫存已經被事務一先讀取,因此這個時候數據庫就阻塞它的讀取,直到事務一提交,事務2才能讀取庫存的值. 幻讀:舉個例子,事務一讀取庫存50件貨,商品庫存初始化爲100,如今已經銷售了50,剩餘50,事務2讀取交易記錄50,事務一扣減庫存,插入交易記錄,提交事務,庫存49件,交易記錄51筆,事務2打印交易記錄51筆,這裏與查詢不一致,在事務2看來有1筆是虛幻的,與以前查詢不一致. 2.3.串行化(serializable),數據庫隔離最高級別,全部sql按順序執行. 提示:能夠在代碼中配置隔離級別. # -1 數據庫默認隔離級別, #1 未提交讀 #2 讀寫提交 #4 可重複讀 #8 串行化 # tomcat 數據源默認隔離級別: Spring.datasource.tomcat.default-transaction-isolation=2 #dbcp2數據庫鏈接池默認隔離級別 Spring.datasource.dbcp2.default-transaction-isolation=2 3.傳播行爲: 在Spring中當一個方法調用另一個方法時,可讓事務採起不一樣的策略工做。 3.1.傳播行爲的定義: REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED):須要事務,它是默認的傳播行爲,若是當前存在事務,就用當前的事務,不然新建一個事務運行子方法. SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS):支持事務,若是當前存在事務,就用當前事務,若是不存在,就繼續採用無事務的方式運行子方法. MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY):必須使用事務,若是當前沒有事務,就會拋出異常,若是存在當前事務,那麼就使用當前事務. REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW):不管當前事務是否存在,都會建立新的事務執行方法,這樣新的事務就能夠擁有新的鎖和隔離級別的特性,與當前事務互相獨立. NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)不支持事務,當前存在事務,將掛起事務,運行方法. NEVER(TransactionDefinition.PROPAGATION_NEVER)不支持事務,若是當前方法有事務,就拋出異常,不然繼續使用無事務機制運行. NESTED(TransactionDefinition.PROPAGATION_NESTED)在當前方法調用子方法時候,若是子方法發生異常,只回滾子方法執行過的sql,而不會滾當前方法的事務. 3.2.@Transactional自調用失效的問題: 類自身的調用是不會產生AOP的,解決方法可使用一個Service去調用另外一個Service,這樣就是代理對象的調用,Spring纔會將你的代碼,放入AOP.