Spring是當前最流行的框架之一,事務管理是我們開發時要處理的主要問題之,來看看Spring是如何讓我們從枯燥無聊的事務管理代碼中脫離出來。
首先我們需要了解數據庫關於事務方面的知識,這裏做個簡單描述:
數據庫事務必須同時滿足4個特性:原子性(Atomic),一致性(Consistency),隔離性(Isolation),持久性(Durabiliy)
1.事務隔離級別
ANSI/ISO SQL 92定義了4個等級的事務隔離級別
隔離級別 | 髒讀 | 不可重複讀 | 幻象讀 | 第一類丟失更新 | 第二類丟失更新 |
READ_UNCOMMITED | Y | Y | Y | N | Y |
READ_COMMITED | N | Y | Y | N | Y |
REPEATABLE_READ | N | N | Y | N | N |
SERIALIZABLE | N | N | N | N | N |
並不是所有的數據庫都支持事務或者支持所有的事務隔離級別,在Java使用JDBC連接數據庫時,我們可以根據Connection的getMetaData獲取一個DataBaseMetaData對象,並可以通過該對象的supportsTransactions(),supportsTransactionIsolationLevel(int level)查看數據庫對事務支持的情況。
Connection是默認提交的,即一條SQL對應一個事務,在程序中爲了保持數據的一致性,我們一般需要講autoCommit設置爲false,當所有操作完成/出現異常時進行顯式的Commit/rollback操作。
2.Spring的事務傳播機制
Spring是如何管理兩個都具有事務的方法呢?Spring的事務傳播機制爲我們詳細的介紹了Spring是如何管理這種狀況的,開發者可以根據情況選擇需要的傳播行爲
<div style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">PROPAGATION_REQUIRED--支持當前事務,如果當前沒有事務,就新建一個事務,如果已存在事務,就加入當前事務(最常使用的一種)。</span></div><div style="text-align: left;"><span style="text-align: center; font-family: Arial, Helvetica, sans-serif;">PROPAGATION_SUPPORTS--支持當前事務,如果當前沒有事務,就以非事務方式執行。</span></div><div style="text-align: left;"><span style="font-family: Arial, Helvetica, sans-serif;">PROPAGATION_REQUIRES_NEW--新建事務,如果當前存在事務,把當前事務掛起。</span></div><div style="text-align: left;"><span style="text-align: center; font-family: Arial, Helvetica, sans-serif;">PROPAGATION_MANDATORY--支持當前事務,如果當前沒有事務,就拋出異常。</span></div><div style="text-align: left;"><span style="text-align: center; font-family: Arial, Helvetica, sans-serif;">PROPAGATION_NOT_SUPPORTED--以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。</span></div><div style="text-align: left;"><span style="text-align: center; font-family: Arial, Helvetica, sans-serif;">PROPAGATION_NEVER--以非事務方式執行,如果當前存在事務,則拋出異常。</span></div><div style="text-align: left;"><span style="text-align: center; font-family: Arial, Helvetica, sans-serif;">PROPAGATION_NE</span><span style="font-family: Arial, Helvetica, sans-serif;">STED--如果當前存在事務,則在嵌套事務內執行,如果沒有事務則執行PROPAGATION_REQUIRED類似的操作</span></div>
Spring默認的事務傳播行爲是PROPAGATION_REQUIRED,也是我們使用最多的情況,它適合絕大多數的情況
3.Spring的聲明式事務
爲什麼我們要選擇聲明式事務?因爲這種方式對代碼的入侵性最小,可以使事務管理代碼完全從業務代碼中剝離,用過Spring聲明式事務管理的開發人員都可以清晰的感覺到,在業務代碼中沒有一絲關於獲取線程綁定,開始事務,提交/回滾事務,異常轉換的處理的代碼
說到這裏我們就不能不說說AOP了,因爲SPring的事務管理代碼就是通過AOP的方式在程序的運行期間動態的編織到我們需要進行事務管理的方法中去的。
下面來讓我們看一個關於聲明式事務的配置
4.Spring單實例化bean
Spring的事務管理器是通過線程相關的ThreadLocal來保存Connection實例,再結合IOC和AOP實現對聲明式事務的管理
Web容器本身即是多線程的,當接收到一個用戶請求會創建一個獨立的線程,所涉及到的Spring容器中的bean也是要運行在多線程的環境下,Spring的bean大多是單實例的(singleton),單實例的bean最大的好處是線程無關,不存在多線程併發問題。一個類能以單實例方式運行的前提是“無狀態”(不能擁有成員變量,運行在多線程下的類的成員變量被線程所共享)