1、事務回顧
(1)、什麼是事務:
事務是邏輯上的一組操作,組成這組操作的各個邏輯單元,要麼一起成功,要麼一起失敗。
(2)、事務特性(ACID)
- 原子性 :強調事務的不可分割
- 一致性 :事務的執行的前後資料的完整性保持一致
- 隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾
- 永續性 :事務一旦結束,資料就持久到資料庫
(3)、事務併發安全性問題
- 髒讀 :一個事務讀到了另一個事務的未提交的資料
- 不可重複讀 :一個事務讀到了另一個事務已經提交的 update 的資料導致多次查詢結果不一致
- 幻讀 :一個事務讀到了另一個事務已經提交的 insert 的資料導致多次查詢結果不一致
(4)、事務隔離級別
- 未提交讀 :髒讀,不可重複讀,幻讀都有可能發生
- 已提交讀 :避免髒讀,但是不可重複讀和幻讀有可能發生
- 可重複讀 :避免髒讀和不可重複讀,但是幻讀有可能發生
- 序列化 :避免以上所有讀問題
(5)、常見資料庫預設事務隔離級別
- MySQL:可重複讀
- Oracle:讀已提交
2、Spring 事務管理
(1)、基本事務操作
- 開啟事務
- 提交事務
- 回滾事務
(2)、事務操作物件
Spring 事務管理中提供了 PlatformTransactionManager 介面操作事務,其中最為核心的物件是 TransactionManager 物件。
(3)、Spring 事務隔離級別
- 讀未提交
- 讀已提交
- 可重複讀
- 序列化
(4)、Spring 事務傳播行為
保證同一個事務中
- PROPAGATION_REQUIRED :支援當前事務,如果不存在 就新建一個(預設)
- PROPAGATION_SUPPORTS :支援當前事務,如果不存在,就不使用事務
- PROPAGATION_MANDATORY :支援當前事務,如果不存在,丟擲異常
保證不在同一個事務中
- PROPAGATION_REQUIRES_NEW :如果有事務存在,掛起當前事務,建立一個新的事務
- PROPAGATION_NOT_SUPPORTED :以非事務方式執行,如果有事務存在,掛起當前事務
- PROPAGATION_NEVER :以非事務方式執行,如果有事務存在,丟擲異常
- PROPAGATION_NESTED :如果當前事務存在,則巢狀事務執行
3、Spring 事務管理方式
(1)、編碼式
- 將核心事務管理器配置到 Spring 容器
<!-- 事務核心管理器,封裝了所有事務操作. 依賴於連線池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name="dataSource" ref="dataSource" ></property>
</bean>
複製程式碼
- 配置TransactionTemplate模板
<!-- 事務模板物件 -->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" >
<property name="transactionManager" ref="transactionManager" ></property>
</bean>
複製程式碼
- 將事務模板注入Service
<!-- 將 demoDao 和事務模板注入 Service-->
<bean name="demoService" class="com.spring.service.demoServiceImpl" >
<property name="dm" ref="demoDao" ></property>
<property name="tt" ref="transactionTemplate" ></property>
</bean>
複製程式碼
- 在Service中呼叫模板
(2)、xml 配置方式
-
匯入所需要的 jar 包和約束
-
配置事務通知
<!-- 配置事務通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
<tx:attributes>
<!-- 以方法為單位,指定方法應用什麼事務屬性
isolation:隔離級別
propagation:傳播行為
read-only:是否只讀
-->
<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
複製程式碼
- 將通知織入目標
<!-- 配置織入 -->
<aop:config >
<!-- 配置切點表示式 -->
<aop:pointcut expression="execution(*com.spring.service.*ServiceImpl.*(..))" id="txPc"/>
<!-- 配置切面 : 通知+切點
advice-ref:通知的名稱
pointcut-ref:切點的名稱
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>
複製程式碼
(3)、註解配置方式
-
匯入所需要的 jar 包和約束
-
開啟註解管理事務
<!-- 開啟使用註解管理事務 -->
<tx:annotation-driven/>
複製程式碼
- 在具體業務中使用註解
掃描關注微信公眾號,瞭解更多