什么是事務?
事務(Transaction),一般是指要做的或所做的事情,在計算機術語中是指訪問並可能更新數據庫中各種數據項的一個程序執行單元.事務通常由高級數據庫曹總語言或編程語言書寫並用形式如begin transaction和end tranaction語句來界定,事務由事務開始和事務結束之間執行的全體操作組成
為什么要事務?
事務事務是為解決數據操作提出的,其實就是控制數據的安全訪問
比如銀行的提款不可能讓你在兩處不同地方同時提所有款的時候提出兩筆錢.
事務的四個特性
- 原子性: 事務是數據庫邏輯工作單位,而且是必須是源自工作單位,對於其數據修改,要么全部執行,要不全不執行.
- 一致性: 事務在完成時,必須所有的數據都保持一直狀態,在相關數據庫中所有規則都必須應用於事務的修改,以保持所有數據的完整性.
- 隔離性: 一個事務的執行不能被其他事務所影響.
- 持久性: 一個事務一旦提交,事務的操作永久性的保存在DB中,幾遍在數據庫系統遇到故障的情況下也不會丟失提交事務的操作.
JDBC事務
在JDBC
中處理事務,都是通過Connection
完成的,同一事務中所有的操作,都在使用同一個Connection
對象.JDBC
事務默認是開啟的,並且默認提交.
JDBC Connection
接口提供了兩種事務模式:自動提交和手工提交
JDBC
中的事務java.sql.Connection
的三個方法與事務有關:
setAutoCommt(bolean): 設置是否自動提交事務,如果true(默認true)表示自動提交,也就是每條執行的SQL語句都是一個單獨的事務,如果設置為false,需要手動提交事務.
commit(): 提交結束事務
rollback(): 回滾事務
傳統JDBC操作流程:
(1) 獲取JDBC連接
(2) 聲明SQL
(3) 預編譯SQL
(4) 執行SQL
(5) 處理結果集
(6) 釋放結果集
(7) 釋放Statement
(8) 提交事務
(9) 處理異常並回滾事務
(10) 釋放JDBC連接
JDBC優缺點 :
1. 冗長,重復
2. 顯示事務控制
3. 每個步驟不可獲取
4. 顯示處理檢查異常
Spring容器事務
Spring事務管理器的實現由許多細節,如果對整個接口框架有個大體了解會非常有利於我們理解事務,下面通過講解Spring的事務接口來了解Spring實現事務的具體策略.
Spring事務管理設計的接口及聯系:
Spring並不直接管理事務,而是提供了多種事務管理器,他們講事務管理的職責委托給Hibernate
或者JTA等JTA等持戒話機制所提供的的相關平台的事務來實現.Spring事務管理器的接口是org.springframework.transaction.PlatformTransactionManager
,通過這個接口,Spring為各個平台如JDBC,Hibernate等都提供了對應的事務管理器,但是具體的實現就是各個平台自己的事情了.
Public interface PlatformTransactionManager{
// 由TransactionDefinition得到TransactionStatus對象
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// 提交
Void commit(TransactionStatus status) throws TransactionException;
// 回滾
Void rollback(TransactionStatus status) throws TransactionException;
}
1 Spring JDBC事務
如果應用程序中直接使用JDBC來進行持久化,
DataSource TransactionManager
會為你處理事務邊界.為了使用DataSourceTransactionManager
,你需要使用如下的XML將其裝配到應用程序的上下文定義中
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
2 Hibernate事務
如果應用程序的持久化是通過
Hibernate
實現的,那么你需要使用HibernateTranscationManager
.對於Hibernate3,
需要在Spring上下文中添加如下的聲明:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
sessionFactory
屬性需要裝配一個Hibernate的session
工廠,HibernateTransactionManager
的實現細節是它將事務管理的職責委托給org.hibernate.Transaction
對象,而后者是從Hibernate Session
中獲取到的。當事務成功完成時,HibernateTransactionManager
將會調用Transaction
對象的commit()
方法,反之,將會調用rollback()
方法。
3 Java持久API事務
Hibernate多年依賴一直是事實上的Java持久化標准,但是現在Java持久化API作為真正的Java持久化標准進入大家的視野.如果你計划使用JPA的話,那你需要使用Spring的JpaTransactionManager來處理事務,你需要在SpringH中這樣的配置JpaTransactionManager:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
****基本的事務屬性的定義:****
事務管理器接口PlatformTransactionManager通過getTransaction(TransactionDefinition definition)方法來得到事務,這個方法里面的參數是TransactionDefinition類,這個類就定義了一些基本的事務屬性。
事務屬性可以理解成事務的一些基本配置,描述了事務策略如何應用到方法上。
****事務屬性包含了5個方面:****
傳播行為、隔離規則、回滾規則、事務超時、是否只讀
TransactionDefinition:
public interface TransactionDefinition { int getPropagationBehavior(); // 返回事務的傳播行為 int getIsolationLevel(); // 返回事務的隔離級別,事務管理器根據它來控制另外一個事務可以看到本事務內的哪些數據 int getTimeout(); // 返回事務必須在多少秒內完成 boolean isReadOnly(); // 事務是否只讀,事務管理器能夠根據這個返回值進行優化,確保事務是只讀的}
7種傳播行為:
****PROPAGATION_REQUIRED:****如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。
****PROPAGATION_SUPPORTS:****支持當前事務,如果當前沒有事務,就以非事務方式執行。
****PROPAGATION_MANDATORY:****支持當前事務,如果當前沒有事務,就拋出異常。
****PROPAGATION_REQUIRES_NEW:****新建事務,如果當前存在事務,把當前事務掛起。
****PROPAGATION_NOT_SUPPORTED:****以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
****PROPAGATION_NEVER:****以非事務方式執行,如果當前存在事務,則拋出異常。
雖然有7種,但是常用的就第一種REQUIRED和第四種REQUIRES_NEW
五個隔離級別:
****ISOLATION_DEFAULT:****這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別.
另外四個與JDBC的隔離級別相對應;
****ISOLATION_READ_UNCOMMITTED:****這是事務最低的隔離級別,它充許別外一個事務可以看到這個事務未提交的數據。
這種隔離級別會產生臟讀,不可重復讀和幻像讀。
****ISOLATION_READ_COMMITTED:****保證一個事務修改的數據提交后才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據。
這種事務隔離級別可以避免臟讀出現,但是可能會出現不可重復讀和幻像讀。
****ISOLATION_REPEATABLE_READ:****這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現幻像讀。
它除了保證一個事務不能讀取另一個事務未提交的數據外,還保證了避免下面的情況產生(不可重復讀)。
****ISOLATION_SERIALIZABLE:****這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
除了防止臟讀,不可重復讀外,還避免了幻像讀。
事務的屬性可同通過注解方式或配置文件配置:
注解方式:
@Transactional只能被應用到public方法上,對於其它非public的方法,如果標記了@Transactional也不會報錯,但方法沒有事務功能.
默認情況下,一個有事務方法, 遇到RuntimeException 時會回滾 . 遇到 受檢查的異常 是不會回滾 的. 要想所有異常都回滾,要加上 @Transactional( rollbackFor={Exception.class,其它異常})
@Transactional( readOnly = false, //讀寫事務 timeout = -1 , //事務的超時時間,-1為無限制 noRollbackFor = ArithmeticException.class, //遇到指定的異常不回滾 isolation = Isolation.DEFAULT, //事務的隔離級別,此處使用后端數據庫的默認隔離級別 propagation = Propagation.REQUIRED //事務的傳播行為)
****配置文件( aop攔截器方式):****
<tx:advice id="advice" transaction-manager="txManager">
<tx:attributes>
<!-- tx:method的屬性:
* name 是必須的,表示與事務屬性關聯的方法名(業務方法名),對切入點進行細化。通配符
(*)可以用來指定一批關聯到相同的事務屬性的方法。
如:'get*'、'handle*'、'on*Event'等等.
* propagation:不是必須的,默認值是REQUIRED表示事務傳播行為,
包括REQUIRED,SUPPORTS,MANDATORY,REQUIRES_NEW,NOT_SUPPORTED,NEVER,NESTED
* isolation:不是必須的 默認值DEFAULT ,表示事務隔離級別(數據庫的隔離級別)
* timeout:不是必須的 默認值-1(永不超時),表示事務超時的時間(以秒為單位)
* read-only:不是必須的 默認值false不是只讀的表示事務是否只讀?
* rollback-for: 不是必須的表示將被觸發進行回滾的 Exception(s);以逗號分開。
如:'com.foo.MyBusinessException,ServletException'
* no-rollback-for:不是必須的表示不被觸發進行回滾的 Exception(s),以逗號分開。
如:'com.foo.MyBusinessException,ServletException'
任何 RuntimeException 將觸發事務回滾,但是任何 checked Exception 將不觸發事務回滾
-->
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT" read-only="false" rollback-for="Exception"/>
<!-- 其他的方法之只讀的 -->
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>