1. 程式人生 > >Java中事務總結詳解(精華)

Java中事務總結詳解(精華)

1.什麼是JAVA事務?

通常的觀念認為,事務僅與資料庫相關。

事務必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)一致性(consistency)隔離性 (isolation)和永續性(durability)的縮寫。

事務的原子性:表示事務執行過程中的任何失敗都將導致事務所做的任何修改失效。
事務的一致性:表示當事務執行失敗時,所有被該事務影響的資料都應該恢復到事務執行前的狀態。
事務的隔離性:表示在事務執行過程中對資料的修改,在事務提交之前對其他事務不可見。
事務的永續性:表示已提交的資料在事務執行失敗時,資料的狀態都應該正確。

通俗的理解,事務是一組原子操作單元,從資料庫角度說,就是一組SQL指令,要麼全部執行成功,若因為某個原因其中一條指令執行有錯誤,則撤銷先前執行過的所有指令。更簡答的說就是:要麼全部執行成功,要麼撤銷不執行

既然事務的概念從資料庫而來,那Java事務是什麼?之間有什麼聯絡?
實際上,一個Java應用系統,如果要操作資料庫,則通過JDBC來實現的。增加、修改、刪除都是通過相應方法間接來實現的,事務的控制也相應轉移到Java程式程式碼中。
因此,資料庫操作的事務習慣上就稱為Java事務。

 

2. 為什麼需要Java事務?

事務是為解決資料安全操作提出的,事務控制實際上就是控制資料的安全訪問。

舉一個簡單例子:
比如銀行轉帳業務,賬戶A要將自己賬戶上的1000元轉到B賬 戶下面,A賬戶餘額首先要減去1000元,然後B賬戶要增加1000元。假如在中間網路出現了問題,A賬戶減去1000元已經結束,
B因為網路中斷而操作 失敗,那麼整個業務失敗,必須做出控制,要求A賬戶轉帳業務撤銷。這才能保證業務的正確性,完成這個操作就需要事務,將A賬戶資金減少和B賬戶資金增加方 
到一個事務裡面,要麼全部執行成功,要麼操作全部撤銷,這樣就保持了資料的安全性。

3.Java事務的型別

Java事務的型別有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務。

1.JDBC事務
JDBC 事務是用 Connection 物件控制的。JDBC Connection 介面( java.sql.Connection )提供了兩種事務模式:自動提交和手工提交。

1 java.sql.Connection 提供了以下控制事務的方法:
2 
3 public void setAutoCommit(boolean)
4 public boolean getAutoCommit()
5 public void
commit() 6 public void rollback()

使用 JDBC 事務界定時,您可以將多個 SQL 語句結合到一個事務中。
JDBC 事務的一個缺點是事務的範圍侷限於一個數據庫連線。一個 JDBC 事務不能跨越多個數據庫。

2.JTA(Java Transaction API)事務

JTA是一種高層的,與實現無關的,與協議無關的API,應用程式和應用伺服器可以使用JTA來訪問事務。

JTA允許應用程式執行分散式事務處理——在兩個或多個網路計算機資源上訪問並且更新資料,這些資料可以分佈在多個數據庫上。JDBC驅動程式的JTA支援極大地增強了資料訪問能力。

如果計劃用 JTA 界定事務,那麼就需要有一個實現 javax.sql.XADataSource 、 javax.sql.XAConnectionjavax.sql.XAResource 介面的 JDBC 驅動程式。一個實現了這些介面的驅動程式將可以參與 JTA 事務。一個 XADataSource 物件就是一個 XAConnection 物件的工廠。 XAConnection s 是參與 JTA 事務的 JDBC 連線。
您將需要用應用伺服器的管理工具設定 XADataSource .從應用伺服器和 JDBC 驅動程式的文件中可以瞭解到相關的指導。
J2EE應用程式用 JNDI 查詢資料來源。一旦應用程式找到了資料來源物件,它就呼叫 javax.sql.DataSource.getConnection() 以獲得到資料庫的連線。
XA 連線與非 XA 連線不同。一定要記住 XA 連線參與了 JTA 事務。這意味著 XA 連線不支援 JDBC 的自動提交功能。同時,應用程式一定不要對 XA 連線呼叫 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() .
相反,應用程式應該使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() .

3.容器事務

容器事務主要是J2EE應用伺服器提供的,容器事務大多是基於JTA完成,這是一個基於JNDI的,相當複雜的API實現。相對編碼實現JTA事務管理, 我們可以通過EJB容器提供的容器事務管理機制(CMT)完成同一個功能,這項功能由J2EE應用伺服器提供。這使得我們可以簡單的指定將哪個方法加入事 務,一旦指定,容器將負責事務管理任務。這是我們土建的解決方式,因為通過這種方式我們可以將事務程式碼排除在邏輯編碼之外,同時將所有困難交給J2EE容 器去解決。使用EJB CMT的另外一個好處就是程式設計師無需關心JTA API的編碼,不過,理論上我們必須使用EJB.

三種Java事務差異?

1、JDBC事務控制的侷限性在一個數據庫連線內,但是其使用簡單。
2、JTA事務的功能強大,事務可以跨越多個數據庫或多個DAO,使用也比較複雜。
3、容器事務,主要指的是J2EE應用伺服器提供的事務管理,侷限於EJB應用使用。

五、總結

Java事務控制是構建J2EE應用不可缺少的一部分,合理選擇應用何種事務對整個應用系統來說至關重要。一般說來,在單個JDBC 連線連線的情況下可以選擇JDBC事務,在跨多個連線或者資料庫情況下,需要選擇使用JTA事務,如果用到了EJB,則可以考慮使用EJB容器事務。

事務(Transaction):是併發控制的單元,是使用者定義的一個操作序列。這些操作要麼都做,要麼都不做,是一個不可分割的工作單位。通過事務,sql server 能將邏輯相關的一組操作繫結在一起,以便伺服器 保持資料的完整性。事務通常是以begin transaction開始,以commit或rollback結束。Commint表示提交,即提交事務的所有操作。具體地說就是將事務中所有對資料的更新
寫回到磁碟上的物理資料庫中去,事務正常結束。Rollback表示回滾,即在事務執行的過程中發生了某種故障,事務不能繼續進行,系統將事務中對資料庫的所有已完成的操作全部撤消,滾回到事務開始的狀態。

自動提交事務:每條單獨的語句都是一個事務。每個語句後都隱含一個commit。 (預設)
顯式事務:以begin transaction顯示開始,以commit或rollback結束。

隱式事務:當連線以隱式事務模式進行操作時,sql server資料庫引擎例項將在提交或回滾當前事務後自動啟動新事務。無須描述事物的開始,只需提交或回滾每個事務。但每個事務仍以commit或rollback顯式結束。連線將隱性事務模式設定為開啟之後,當資料庫引擎例項首次執行下列任何語句時,都會自動啟動一個隱式事務:alter table,insert,create,open ,delete,revoke ,drop,select, fetch ,truncate table,grant,update在發出commit或rollback語句之前,該事務將一直保持有效。在第一個事務被提交或回滾之後,下次當連線執行以上任何語句時,資料庫引擎例項都將自動啟動一個新事務。該例項將不斷地生成隱性事務鏈,直到隱性事務模式關閉為止。

Java JDBC事務機制

首先,我們來看看現有JDBC操作會給我們打來什麼重大問題,比如有一個業務:當我們修改一個資訊後再去查詢這個資訊,看是這是一個簡單的業務,實現起來也非常容易,但當這個業務放在多執行緒高併發的平臺下,問題自然就出現了,比如當我們執行了一個修改後,在執行查詢之前有一個執行緒也執行了修改語句,這是我們再執行查詢,看到的資訊就有可能與我們修改的不同,為了解決這一問題,我們必須引入JDBC事務機制,其實程式碼實現上很簡單,一下給出一個原理實現例子供大家參考:

 1 private Connection conn = null;  
 2 
 3 private PreparedStatement ps = null;  
 4 
 5 try {  
 6 
 7 
 8 
 9     conn.setAutoCommit(false);  //將自動提交設定為false  
10 
11     ps.executeUpdate("修改SQL"); //執行修改操作  
12 
13     ps.executeQuery("查詢SQL");  //執行查詢操作                 
14 
15     conn.commit();      //當兩個操作成功後手動提交  
16 
17 } catch (Exception e) {  
18 
19     conn.rollback();    //一旦其中一個操作出錯都將回滾,使兩個操作都不成功  
20 
21     e.printStackTrace();  
22 
23 }

與事務相關的理論

1.事務(Transaction)的四個屬性(ACID)

原子性(Atomic) 對資料的修改要麼全部執行,要麼全部不執行。
一致性(Consistent) 在事務執行前後,資料狀態保持一致性。
隔離性(Isolated) 一個事務的處理不能影響另一個事務的處理。
持續性(Durable) 事務處理結束,其效果在資料庫中持久化。

2.事務併發處理可能引起的問題

髒讀(dirty read):一個事務讀取了另一個事務尚未提交的資料,
不可重複讀(non-repeatable read) :一個事務的操作導致另一個事務前後兩次讀取到不同的資料
幻讀(phantom read) :一個事務的操作導致另一個事務前後兩次查詢的結果資料量不同。

舉例:

事務A、B併發執行時,當A事務update後,B事務select讀取到A尚未提交的資料,此時A事務rollback,則B讀到的資料是無效的”髒”資料。
當B事務select讀取資料後,A事務update操作更改B事務select到的資料,此時B事務再次讀去該資料,發現前後兩次的資料不一樣。
當B事務select讀取資料後,A事務insert或delete了一條滿足A事務的select條件的記錄,此時B事務再次select,發現查詢到前次不存在的記錄(“幻影”),或者前次的某個記錄不見了。

JDBC的事務支援

JDBC對事務的支援體現在三個方面:

1.自動提交模式(Auto-commit mode)
Connection提供了一個auto-commit的屬性來指定事務何時結束。
a.當auto-commit為true時,當每個獨立SQL操作的執行完畢,事務立即自動提交,也就是說每個SQL操作都是一個事務。一個獨立SQL操作什麼時候算執行完畢。

1.JDBC規範是這樣規定的:對資料操作語言(DML,如insert,update,delete)和資料定義語言(如create,drop),語句一執行完就視為執行完畢。
2.對select語句,當與它關聯的ResultSet物件關閉時,視為執行完畢。
3.對儲存過程或其他返回多個結果的語句,當與它關聯的所有ResultSet物件全部關閉,所有update count(update,delete等語句操作影響的行數)和output parameter(儲存過程的輸出引數)都已經獲取之後,視為執行完畢。

b. 當auto-commit為false時,每個事務都必須顯示呼叫commit方法進行提交,或者顯示呼叫rollback方法進行回滾。auto-commit預設為true。


2.事務隔離級別(Transaction Isolation Levels)
JDBC提供了5種不同的事務隔離級別,在Connection中進行了定義。
JDBC定義了五種事務隔離級別:

TRANSACTION_NONE JDBC驅動不支援事務
TRANSACTION_READ_UNCOMMITTED 允許髒讀、不可重複讀和幻讀。
TRANSACTION_READ_COMMITTED 禁止髒讀,但允許不可重複讀和幻讀。
TRANSACTION_REPEATABLE_READ 禁止髒讀和不可重複讀,單執行幻讀。
TRANSACTION_SERIALIZABLE 禁止髒讀、不可重複讀和幻讀。

3.儲存點(SavePoint)

JDBC定義了SavePoint介面,提供在一個更細粒度的事務控制機制。當設定了一個儲存點後,可以rollback到該儲存點處的狀態,而不是rollback整個事務。

Connection介面的setSavepoint和releaseSavepoint方法可以設定和釋放儲存點。
JDBC規範雖然定義了事務的以上支援行為,但是各個JDBC驅動,資料庫廠商對事務的支援程度可能各不相同。如果在程式中任意設定,可能得不到想要的效果。為此,JDBC提供了DatabaseMetaData介面,提供了一系列JDBC特性支援情況的獲取方法。比如,通過DatabaseMetaData.supportsTransactionIsolationLevel方法可以判斷對事務隔離級別的支援情況,通過DatabaseMetaData.supportsSavepoints方法可以判斷對儲存點的支援情況。