事務的基本原理
- Spring事務的本質其實就是數據庫對事務的支持。
- 事務是一系列的動作,一旦其中有一個動作出現錯誤,必須全部回滾,系統將事務中對數據庫的所有已完成的操作全部撤銷,回滾到事務開始的狀態,避免出現由於數據不一致而導致的接下來一系列的錯誤。事務的出現是爲了保證數據的完整性以及一致性,在目前企業級應用開發中,事務管理是必不可少的。
事務的四大特性(ACID)
- 原子性(Atomicity):事務是一個原子操作,由一系列動作組成。操作要麼全部完成,要麼全部不完成。
- 一致性(Consistency):事務在完成時,所有的數據都必須保持一致狀態。
- 隔離性(Isolation):當前事務不收併發事務執行的影響。在一個事務內部的操作對其他事務是不產生影響,需要事務隔離級別來指定隔離性。
- 持久性(Durability):一旦事務完成,數據庫的改變必須是持久化的。
事務併發引起問題
- 事務的併發:在企業級應用中,多用戶訪問數據庫是常見的場景。存在問題如下
- 髒讀:一個事務讀到另一個事務未提交的更新數據。
- 不可重複讀:一個事務兩次讀同一行數據,可這兩次讀取到的數據不一樣。
- 幻讀:一個事務執行兩次查詢,但第二次查詢比第一次查詢多出了一些數據行。
- 丟失更新:撤銷一個事務時,把其他事務已提交的更新數據覆蓋了。
- JDBC隔離級別:
- TRANSACTION_NONE JDBC:驅動不支持事務
- TRANSACTION_READ_UNCOMMITTED:允許髒讀、不可重複讀和幻讀。
- TRANSACTION_READ_COMMITTED:禁止髒讀,但允許不可重複讀和幻讀。
- TRANSACTION_REPEATABLE_READ:禁止髒讀和不可重複讀,單運行幻讀。
- TRANSACTION_SERIALIZABLE:禁止髒讀、不可重複讀和幻讀。
- 隔離級別越高,意味着數據庫事務併發執行的性能越差,能處理的操作就越少。
Spring事務管理
- Spring事務管理的核心接口是Platform TransactionManager,事務管理器接口通過getTransaction方法根據指定的傳播行爲返回當前活動的事務或者創建一個新的事務。
Spring事務的傳播屬性
名稱 | 值 | 解釋 |
---|---|---|
PROPAGATION_REQUIRED | 0 | 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇,也是Spring默認的事務的傳播。 |
PROPAGATION_SUPPORTS | 1 | 支持當前事務,如果當前沒有事務,就以非事務方式執行。 |
PROPAGATION_MANDATORY | 2 | 支持當前事務,如果當前沒有事務,就拋出異常。 |
PROPAGATION_REQUIRES_NEW | 3 | 新建事務,如果當前存在事務,把當前事務掛起。 |
PROPAGATION_NOT_SUPPORTED | 4 | 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。 |
PROPAGATION_NEVER | 5 | 以非事務方式執行,如果當前存在事務,則拋出異常。 |
PROPAGATION_NESTED | 6 | 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。 |
Spring事務的隔離級別
名稱 | 值 | 解釋 |
---|---|---|
ISOLATION_DEFAULT | -1 | 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別。另外四個與JDBC的隔離級別相對應 |
ISOLATION_READ_UNCOMMITTED | 1 | 這是事務最低的隔離級別,它充許另外一個事務可以看到這個事務未提交的數據。這種隔離級別會產生髒讀,不可重複讀和幻讀。 |
ISOLATION_READ_COMMITTED | 2 | 保證一個事務修改的數據提交後才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據。 |
ISOLATION_REPEATABLE_READ | 4 | 這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻讀。 |
ISOLATION_SERIALIZABLE | 8 | 這是花費最高代價但是最可靠的事務隔離級別。事務被處理爲順序執行。除了防止髒讀,不可重複讀外,還避免了幻讀。 |
配置事務管理器
-
<!-- 配置事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
-
Spring提供了兩種事務管理的方式:編程式事務管理和聲明式事務管理
編程式事務管理
-
通過
Platform TransactionManager
實現事務管理,同樣Spring提供了模板類TransactionTemplate進行事務管理。 -
<!--配置事務管理的模板--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"></property> <!--定義事務隔離級別,-1表示使用數據庫默認級別--> <property name="isolationLevelName" value="ISOLATION_DEFAULT"></property> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property> </bean>
-
在代碼中使用:注入
TransactionTemplate
類,然後調用其execute
,重寫doInTransactionWithoutResult
方法即可,如下-
@Resource private TransactionTemplate transactionTemplate; transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { try{ baseSevice.insert("INSERT INTO tbl_account VALUES (100);",false); } catch (Exception e){ //對於拋出Exception類型的異常且需要回滾時,需要捕獲異常並通過調用status對象的setRollbackOnly()方法告知事務管理器當前事務需要回滾 status.setRollbackOnly(); e.printStackTrace(); } } });
-
-
優缺點:編程方式管理事務,極大靈活性,難維護。
聲明式事務管理
-
聲明式事務管理有兩種常用的方式
- 基於tx和aop命名空間的xml配置文件
- 基於@Transactional註解
-
基於tx和aop命名空間的xml配置文件
-
配置文件:
<tx:advice id="advice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="insert" propagation="REQUIRED" read-only="false" rollback-for="Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pointCut" expression="execution (* com.tmf.service.*.*(..))"/> <aop:advisor advice-ref="advice" pointcut-ref="pointCut"/> </aop:config>
-
-
基於@Transactional註解
-
這種方式是最簡單,也是最爲常用的,只需要在配置文件中開啓對註解事務管理的支持。如下:
<!-- 聲明式事務管理 配置事物的註解方式注入--> <tx:annotation-driven transaction-manager="transactionManager"/>
-
然後在需要事務管理的地方加上@Transcational註解:
@Transactional(rollbackFor=Exception.class)
-
rollbackFor屬性指定出現Exception異常的時候回滾,遇到檢查性的異常需要回滾,默認情況下非檢查性異常,包括error也會自動回滾。
-