DataSource學習

在 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 的新的異常,這個異常說明批處理操作中至少有一條命令失敗了。這樣,您就需要在批處理操作中增加一個適當的異常處理程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章