在 Java 應用程序和數據庫之間創建連接的過程的第一步是用“Java 虛擬機”(Java virtual machine(JVM))註冊 JDBC 驅動程序,Java 應用程序就是在此 JVM 中運行的。在傳統的連接機制(相對於後面中討論的 DataSource
連接機制)中,連接和所有數據庫通訊是由 DriverManager
對象控制的。要建立一個連接,必須用 DriverManager
對象註冊針對目標數據庫的適當的 JDBC 驅動程序。
事務基礎
在單用戶模式,事務非常容易理解 — 它們只是和保存或忘記應用程序的狀態有關。然而,在多用戶模式中,事務變得複雜多了。多用戶事務的經典說明是銀行帳戶,其中一個應用程序試圖在借記帳戶,同時另一個應用程序試圖貸記同一個帳戶。如果您熟悉併發編程(也叫作多線程編程),您以前可能見過這種問題。根本的問題是除非兩個事務相互隔離,否則一個應用程序就可能影響另一個,從而導致錯誤的程序狀態。在我們簡單的說明中,這可能意味着一個帳戶中有錯誤的金額,這將無益於留住客戶。
當處理多個訪問相同數據的用戶時,通常可能出現三種問題:
- 髒讀。當應用程序使用了被另一個應用程序修改過的數據,而這個數據處於未提交狀態時,就會發生髒讀。第二個應用程序隨後會請求回滾被其修改的數據。第一個事務使用的數據就會被損壞,或者“變髒”。
- 不可重複的讀。當一個事務獲得了數據,而該數據隨後被一個單獨的事務所更改時,若第一個事務再次讀取更改後的數據,就會發生不可重複的讀。這樣,第一個事務進行了一個不可重複的讀。
- 虛讀。當事務通過某種查詢獲取了數據,另一個事務修改了部分該數據,原來的事務第二次獲取該數據時,就會發生虛讀。第一個事務現在會有不同的結果集,它可能包含虛讀。
事務級別
爲了解決與“多個線程請求相同數據”相關的問題,事務之間用鎖相互隔開。多數主流的數據庫支持不同類型的鎖;因此,JDBC API 支持不同類型的事務,它們由 Connection
對象指派或確定。在 JDBC API 中可以獲得下列事務級別:
TRANSACTION_NONE
說明不支持事務。TRANSACTION_READ_UNCOMMITTED
說明在提交前一個事務可以看到另一個事務的變化。這樣髒讀、不可重複的讀和虛讀都是允許的。TRANSACTION_READ_COMMITTED
說明讀取未提交的數據是不允許的。這個級別仍然允許不可重複的讀和虛讀產生。TRANSACTION_REPEATABLE_READ
說明事務保證能夠再次讀取相同的數據而不會失敗,但虛讀仍然會出現。TRANSACTION_SERIALIZABLE
是最高的事務級別,它防止髒讀、不可重複的讀和虛讀。
您可能想知道,爲什麼不是所有事務都運行在 TRANSACTION_SERIALIZABLE
模式以保證最高程度的數據完整性呢?問題在於,和處理多線程編程有關的問題相似,事務保護的級別越高,性能損失就越大。
假定您的數據庫和 JDBC 驅動程序支持這個特性,則給定一個 Connection
對象,您可以明確地設置想要的事務級別:
con.setTransactionLevel(TRANSACTION_SERIALIZABLE) ;
您還可以確定當前事務的級別:
if(con.getTransactionLevel() == TRANSACTION_SERIALIZABLE) System.out.println("Highest Transaction Level in operation.") ;
很多數據庫支持批處理操作,在批處理操作中通過在一次單獨的操作(或批處理)中執行多個數據庫更新操作,開銷可被最小化。批處理操作在 JDBC 2.0 中被引入,它要求事務不處於自動提交模式。下面的示例中說明了批處理操作,其中假定包含一個簡單表的數據庫中存在一個 Connection
。
con.setAutoCommit(false) ;
Statement stmt = connection.createStatement() ;
stmt.addBatch("INSERT INTO people VALUES('Joe Jackson', 0.325, 25, 105) ;
stmt.addBatch("INSERT INTO people VALUES('Jim Jackson', 0.349, 18, 99) ;
stmt.addBatch("INSERT INTO people VALUES('Jack Jackson', 0.295, 15, 84) ;
int[] updateCounts = stmt.executeBatch() ;
con.commit() ;
注意,executeBatch()
方法返回一個更新計數的數組,每個值對應於批處理操作的一個命令。關於批處理操作的最後一個問題是,它們可能拋出一個類型爲 BatchUpdateException
的新的異常,這個異常說明批處理操作中至少有一條命令失敗了。這樣,您就需要在批處理操作中增加一個適當的異常處理程序。