事務就是将一系列的動作當做一個單獨的工作單元. 這些動作要麼全部完成, 要麼全部不管用
事務的四個關鍵屬性(ACID):
–原子性(atomicity): 事務是一個原子操作, 由一系列動作組成. 事務的原子性確定動作要麼全部完成要麼完全不起作用.
–一緻性(consistency): 一旦所有事務動作完成, 事務就被送出. 資料和資源就處于一種滿足業務規則的一緻性狀态中.
–隔離性(isolation): 可能有許多事務會同時處理相同的資料, 是以每個事物都應該與其他事務隔離開來, 防止資料損壞.
–持久性(durability): 一旦事務完成, 無論發生什麼系統錯誤, 它的結果都不應該受到影響. 通常情況下, 事務的結果被寫到持久化存儲器中.
配置事務三步驟:
- 配置事務管理器,
- 配置注解驅動,
- 在方法上加入@Transactional注解
<!-- 配置事務管理器 -->
<!--jdbc事務管理器是DataSourceTransactionManager
Hibernate的事務管理器是HibernateTransactionManager-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 啟用事務注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
事務傳播屬性
當事務方法被另一個事務方法調用時, 必須指定事務應該如何傳播. 例如: 方法可能繼續在現有事務中運作, 也可能開啟一個新事務, 并在自己的事務中運作
下圖是預設情況
用XML方式配置事務
<!-- 1. 配置事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2. 配置事務屬性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 根據方法名指定事務的屬性 -->
<tx:method name="purchase" propagation="REQUIRES_NEW"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 3. 配置事務切入點, 以及把事務切入點和事務屬性關聯起來 -->
<aop:config>
<aop:pointcut expression="execution(* com.atguigu.spring.tx.xml.service.*.*(..))"
id="txPointCut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
事務的隔離級别
當同一個應用程式或者不同應用程式中的多個事務在同一個資料集上并發執行時, 可能會出現許多意外的問題
并發事務所導緻的問題可以分為下面三種類型:
–髒讀: 對于兩個事物 T1, T2, T1 讀取了已經被 T2 更新但 還沒有被送出的字段. 之後, 若 T2 復原, T1讀取的内容就是臨時且無效的.
–不可重複讀:對于兩個事物 T1, T2, T1 讀取了一個字段, 然後 T2 更新了該字段. 之後, T1再次讀取同一個字段, 值就不同了.
–幻讀:對于兩個事物 T1, T2, T1 從一個表中讀取了一個字段, 然後 T2 在該表中插入了一些新的行. 之後, 如果 T1 再次讀取同一個表, 就會多出幾行.
從理論上來說, 事務應該彼此完全隔離, 以避免并發事務所導緻的問題. 然而, 那樣會對性能産生極大的影響, 因為事務必須按順序運作.