一、DataSource接口是一個更好的連接數據源的方法:
JDBC1.0是原來是用DriverManager類來產生一個對數據源的連接。JDBC2.0用一種替代的方法,使用DataSource的實現,代碼變的更小巧精致,也更容易控制。
一個DataSource對象代表了一個真正的數據源。根據DataSource的實現方法,數據源既可以是從關系數據庫,也電子表格,還可以是一個表格形式的文件。當一個DataSource對象注冊到名字服務中,應用程序就可以通過名字服務獲得DataSource對象,并用它來產生一個與DataSource代表的數據源之間的連接。
關于數據源的信息和如何來定位數據源,例如數據庫服務器的名字,在哪臺機器上,端口號等等,都包含在DataSource對象的屬性里面去了。這樣,對應用程序的設計來說是更方便了,因為并不需要硬性的把驅動的名字寫死到程序里面去。通常驅動名字中都包含了驅動提供商的名字,而在DriverManager類中通常是這么做的。如果數據源要移植到另一個數據庫驅動中,代碼也很容易做修改。所需要做的修改只是更改DataSource的相關的屬性。而使用DataSource對象的代碼不需要做任何改動。
由系統管理員或者有相應權限的人來配置DataSource對象。配置DataSource,包括設定DataSource的屬性,然后將它注冊到JNDI名字服務中去。在注冊DataSource對象的的過程中,系統管理員需要把DataSource對象和一個邏輯名字關聯起來。名字可以是任意的,通常取成能代表數據源并且容易記住的名字。在下面的例子中,名字起為:InventoryDB,按照慣例,邏輯名字通常都在jdbc的子上下文中。這樣,邏輯名字的全名就是:jdbc/ InventoryDB。
一旦配置好了數據源對象,應用程序設計者就可以用它來產生一個與數據源的連接。下面的代碼片段示例了如何用JNDI上下文獲得一個一個數據源對象,然后如何用數據源對象產生一個與數據源的連接。開始的兩行用的是JNDI API,第三行用的才是JDBC的API:
Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/InventoryDB");Connection con = ds.getConnection("myPassword", "myUserName");
在一個基本的DataSource實現中,DataSource.getConnection方法返回的Connection對象和用DriverManager.getConnection方法返回的Connection對象是一樣的。因為DataSource提供的方便性,我們推薦使用DataSource對象來得到一個Connection對象。我們希望所以的基于JDBC2.0技術的數據庫驅動都包含一個基本的DataSource的實現,這樣就可以在應用程序中很容易的使用它。
對于普通的應用程序設計者,是否使用DataSource對象只是一個選擇問題。但是,對于那些需要用的連接池或者分布式的事務的應用程序設計者來說,就必須使用DataSource對象來獲得Connection,原因在下面我們會提到。
二、Connection pooling(連接池):
連接池是這么一種機制,當應用程序關閉一個Connection的時候,這個連接被回收,而不是被destroy,因為建立一個連接是一個很費資源的操作。如果能把回收的連接重新利用,會減少新創建連接的數目,顯著的提高運行的性能。
假設應用程序需要建立到一個名字為EmpolyeeDB的DataSource的連接。使用連接池得到連接的代碼如下:
Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/EmployeeDB");Connection con = ds.getConnection("myPassword", "myUserName");除了邏輯名字以外,我們發現其代碼和上面舉的例子的代碼是一樣的。邏輯名字不同,就可以連接到不同的數據庫。DataSource對象的getConnection方法返回的Connection是否是一個連接池中的連接完全取決于DataSource對象的實現方法。如果DataSource對象實現與一個支持連接池的中間層的服務器一起工作,DataSource對象就會自動的返回連接池中的連接,這個連接也是可以重復利用的。
是否使用連接池獲得一個連接,在應用程序的代碼上是看不出不同的。在使用這個Connection連接上也沒有什么不一樣的地方,唯一的不同是在java的finally語句塊中來關閉一個連接。在finally中關閉連接是一個好的編程習慣。這樣,即使方法拋出異常,Connection也會被關閉并回收到連接池中去。代碼應該如下所示:
try{…
}catch(){…
}finally{ if(con!=null)con.close();}
三、分布式事務:
獲得一個用來支持分布式事務的連接與獲得連接池中的連接是很相似的。同樣,不同之處在于DataSource的實現上的不同,而不是在應用程序中獲得連接的方式上有什么不同。假設DataSource的實現可以與支持分布式事務中間層服務器一起工作,得到連接的代碼還是如下所示:
Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/EmployeeDB"); Connection con = ds.getConnection("myPassword", "myUserName");由于性能上的原因,如果一個DataSource能夠支持分布式的事務,它同樣也可以支持連接池管理。
從應用程序設計者的觀點來看。是否支持分布式的事務的連接對它來說沒什么不同,唯一的不同是在事務的邊界上(開始一個事務的地方和結束一個事務的地方),開始一個事務或者結束一個事務都是由事務服務器來控制的。應用程序不應該做任何可能妨礙服務的事情。應用程序不能夠直接調用事務提交commit或者回滾rollback操作,也不能夠使用事務的自動提交模式auto-commit mode(在數據庫操作完成的時候自動的調用commit或者rollback)。
在一個連接參與了分布式事務的時候,下面的代碼是你不能做的(con表示支持分布式事務的連接Connection)。
con.commit();或者con.rollback();或者con.setAutoCommit(true);對于通常的Connection來說,缺省的是auto-commit模式。而對于支持分布式事務的Connection來說,缺省不是auto-commit模式。注意,即使Connection是支持事務的,它也可以用于沒有事務的情況。關于事務邊界的限制只是是對分布式事務的情況下才成立的。
配置支持連接池的DataSource的時候,涉及到配置ConnectionPoolDataSource對象,這個對象是三層體系結構中的中間層來管理連接池的。同樣的,在配置支持分布式事務的時候,需要配置XADataSource,XADataSource是中間層用來管理分布式事物的對象。ConnectionPoolDataSource和XADataSource是由驅動提供商提供的,對應用程序的設計者來說是透明的。和基本的DataSource一樣,系統管理員來配置ConnectionPoolDataSource和XADataSource對象。
四、結果集(RowSet接口):
結果集對象是一行行數據的容器。根據其目的,可以通過多種方法實現。RowSet及其相關的接口與JDBC2.0的標準擴展API有點不同,他們并不是驅動的一部分,RowSet是在驅動的上層實現的,可以由其它的任何人來實現他們。
任何類型的rowset都實現了RowSet接口,RowSet接口擴展了ResultSet接口。這樣RowSet對象就有了ResultSet對象所有的功能。能夠通過getXXX方法得到數據庫中的某列值,通過updateXXX方法可以修改某列值,可以移動光標,是當前行變為另一行。
當然,我們更感興趣的是RowSet接口提供的新的功能。作為一個JavaBean組件,RowSet對象可以增加或者刪除一個listener(監聽者),可以get或者set其屬性值,這些屬性中,有一個是字符串,表示一個對數據庫Query請求,RowSet接口定義了設定參數的方法,也提供了執行這個請求的方法。這意味著RowSet對象能夠執行查詢請求,可以根據它產生的結果集進行計算。同樣,RowSet也可以根據任何表格數據源進行計算,所以,它不局限于關系數據庫。
從數據源得到數據之后,RowSet對象可以和數據源斷開連接,rowset也可以被序列化。這樣,RowSet就可以通過網絡傳遞給瘦客戶端。
RowSet可以被重新連接到數據源,這樣,做的修改就可以存回到數據源中去。如果產生了一個listener,當RowSet的當前行移動,或者數據被修改的時候,監聽者就會收到通知。例如,圖形用戶界面組件可以注冊成為監聽者,當RowSet更改的時候,圖形用戶界面接到通知,就可以修改界面,來符合它所表示的RowSet。
根據不同的需要,RowSet接口可以通過多種方法來實現。Java software已經寫了一個CachedRowSet實現,從http://developer.java.sun.com/developer/earlyAccess/crs/index.html中可以得到這個實現。
與CachedRowSet類不樣的是,JDBCRowSet類總是保持一個和數據源的連接。這樣,在ResultSet外圍簡單到加了一層,是基于JDBC技術的驅動看起來象是一個簡單的JavaBean組件一樣。
總結:JDBC2.0標準擴展API通過見DataSource注冊到JNDI名字服務上,將JDBC技術擴展為一個全新的概念。使應用程序的代碼更加精巧,易于控制。新的API支持了連接池,支持分布式的事務。最后,還使java應用程序可以在網絡上傳播結果集,是不可以滾動的ResultSet變成了可以滾動的RowSet。