第1部分:應用程序連接數據的簡單方法
前言
你想不想寫自己的JDBC驅動,或者是否想把現在的JDBC驅動轉換成Type3的驅動呢?Type3 的驅動主要用於無需客戶端設置的Internet/Intrant應用程序中,並且提供靈活的系統管理工具。本文中Nitin Nanda 和 Sunil Kumar描述了JDBC驅動的架構並概略講解了Type3 JDBC驅動的三層結構。並演示了如何創建自己的Type3 JDBC驅動。
在Java中訪問數據庫系統你需要一個JDBC驅動。你可以自己寫Type1到Type4的JDBC驅動,可以是純Java的方式或者使用Java結合本地接口方法的復合方式。產品化的方式趨向於利用純Java技術創建Type3或Type4的驅動程序。在Internet應用程序中訪問數據庫的效率和穩定性成為了關鍵因素,這時Type3 JDBC驅動顯示出了它的優勢。所以,要開發高效的、易部署的Internet應用,你通常需要將現在的Type1或Type2類型的JDBC替換成Type3類型的。
整個文章分為3個部分:
1. 應用程序連接數據庫的簡單方法。
2. 使用自定義的JDBC驅動編譯、部署、訪問數據。
3. 通過高級的日志功能、連接池、預處理數據集增強自定義的JWDriver的性能。
在這三個部分中,我們首先介紹了我們自己的Type3 JDBC驅動的結構和設計(第一部分),然後講了如何實現和部署整個驅動(第二部分),最後講解了如何在其中增加一些高級特性,比如SQL日志、連接池等(第三部分)。
注意:
在開始之前,也許你可以先看一下Nitin Nanda"s的"JDBC Drivers in the Wild",這更有利於你理解JDBC驅動。
JDBC驅動的結構
JDBC為通用的數據庫訪問提供了一種程序級的接口。在一個特定的數據庫環境下使用JDBC API你需要一個JDBC驅動來完成他們直接的協調運行。JDBC被分為四種類型或者說層次。每一個類型都有一個JDBC實現,以便滿足日益增加的對平台獨立性、執行效率和可管理性的要求。這四種類型分別是:
Type1:JDBC-ODBC(開方數據庫連接)橋。
Type2:本地API,部分的Java驅動。
Type3:網絡協議,完全的Java 驅動。
Type4:本地協議,完全的Java驅動。
所有的JDBC驅動都要實現下面四個JDBC類:Driver、Connection、Statement和ResultSet。包含在Java.sql包種DriverManager類用於管理被加載的驅動。客戶端應用程序通過它獲得數據庫連接。JDBC的Driver通過下面的方法加載:
Class.forName("com.jw.clIEnt.JWDriver");
當這個Driver被加載時它的staic部分的代碼就會執行,通過DriverManager注冊這個驅動。現在,只要客戶端應用程序通過DriverManger.getConnection()方法,DriverManager就會轉而調用Driver.connect()方法。每一個JDBC驅動必須實現Java.sql.Driver接口。所以,JDBC驅動的Driver.connect方法會首先檢測當前的驅動Url是否正確,然後會通過connet()方法返回一個Connection對象。
簡單Type3驅動的結構
為了向你展示Type3驅動的內容結構,我創建了一個自己的Type3JDBC驅動。我們的Type3驅動是基於網絡協議、完全Java實現的,它分為3個層次,同時向你展示了JDBC是如何通過中間層的網絡協議進行通信的。中間層服務講請求傳輸(直接或間接的)給特定的數據庫本地連接接口,然後通過這個接口將請求傳輸到數據庫服務器。中間層用Java實現,數據庫訪問的實現通過JDBC-ODBC橋。
JDBC Type3 的結構
對於applet,客戶層驅動文件位於中間層服務器,並且可以直接下載。在JDBC驅動種RMI提供網絡協議服務,負責驅動的客戶端和服務端的通信。JDBC-ODBC橋使得JDBC請求可以傳輸到數據庫服務器。
驅動的客戶層為客戶端程序提供了標准的JDBC接口,包括實現了Java.sql.Driver接口的Driver類。同時還包含了JDBC的Connection、Statement、Result接口的實現。
客戶端應用程序,比如applet,可以使用Type3驅動的客戶層類進行開發,因為它實現了標准的JDBC接口擁有標准的JDBC功能。客戶層類的Driver在內部會維護與中間層提供的遠程接口之間的通信。這些遠程接口提供了客戶端傳輸JDBC請求要用到的基本方法。應用程序會調用已經實現了的Driver中的JDBC方法,隨後這些調用會通過RMI發送到中間層。所有Driver類的客戶層通過中間層來管理內部的RMI通信。
驅動的服務層是一個RMI服務器,它通過JDBC-ODBC橋來和數據庫進行通信。驅動的服務層包含4個遠程接口以及它們的實現,這些遠程接口分別為JDBC的Driver、Connection、Statement和Result提供了訪問接口。實現這些遠程接口的類會在內部維護JDBC-ODBC的橋驅動的Connection、Statement和Result對象。當客戶層類調用遠程接口的時候,遠程接口的實現使用內部的JDBC對象與數據庫通訊。
現在你已經了解了Type3 JDBC驅動的接口,下面讓我們進一步的深入到客戶層和服務器層中。
JDBC類驅動
為了實現Type3 JDBC驅動,我們必須創建客戶層和中間層。客戶層類位於com.jw.clIEnt包中,中間層位於com.jw.server包中,讓我們先來看看客戶層。
客戶層類
客戶層包com.jw.clIEnt中包含下面幾個類:
com.jw.clIEnt.JWDriver類:JDBC驅動(Driver)的實現類。
com.jw.clIEnt.JWConnection類:JDBC連接(Connection)的實現類。
com.jw.clIEnt.JWStatement類:JDBC表達式(Statement)的實現類。
com.jw.clIEnt.JWRseultSet類:JDBC結果集(ResultSet)的實現。
如所示,它描述了客戶層和中間層Driver和Connection類之間的關系。
Driver和Connection類
讓我們仔細的看看JWDriver類的內部:
JWDriver類
com.jw.clIEnt.JWDriver類實現了Java.sql.Driver接口,它提供了通過DriverManager類注冊自己並創建數據庫連接的方法。這個類實現了遠程Driver的封裝以便提供JDBC驅動接口。在應用程序中通過下面的方法調用可以加載JWDriver:
Class.forName("com.jw.clIEnt.JWDriver");
當它通過DriverManager類加載後,上面的代碼中forName方法會調用JWDriver類的static部分的代碼。下面顯示的代碼中的static部分:
static{try{// Register the JWDriver with DriverManagerJWDriver driverInst = new JWDriver();DriverManager.registerDriver(driverInst);System.setSecurityManager(new RMISecurityManager());}...}
JWDriver類同時還維護一個遠程驅動的引用,com.jw.server.IremoteDriver,它位於中間層服務器。遠程驅動的引用為JWDriver創建了數據庫的連接。所以當應用程序需要獲得一個數據庫連接的時候就調用DriverManager.getConnection()方法,這時DriverManager的JWDriver.connect()方法會通過遠程驅動的引用獲得一個數據庫連接。
簡而言之,JWDriver.connect()方法完成如下超作:
l 比較客戶端程序傳遞的URL如果是一個不匹配的URL就返回一個null。
l 如果不存在遠程驅動引用就通過Naming.lookup()方法創建一個。JWDriver.connet()方法控制遠程驅動來創建數據庫連接。:
if(remoteDriver == null){remoteDriver= RemoteDriver)Naming.lookup("rmi://"+serverName+":1099"+"/RemoteDriver");}
l 創建、使用如上方法創建的數據庫連接,並將創建的數據庫連接返回給調用它的應用程序。RemoteDriver.getConnetion()方法是中間層JDBC驅動的遠程調用,從中間層獲得的遠程Connection作為一個應用保存在JWConnection類對象中。JWConnection類可以通過下面的方法獲得:
{IRemoteConnection remoteConInstance =(IRemoteConnection)remoteDriver.getConnection();localConInstance = new JWConnection(remoteConInstance);...return (Connection)localConInstance;}
下面我們一起來仔細的看看JWConnection類。
JWConnection類
Com.jw.clIEnt.JWConnection類實現了Connection接口,而且它還包含一個遠程服務器IremoteConnection接口的引用。
客戶端程序中的JWDriver.connect方法可以得到JWConnection對象的引用並創建一個JWConnection對象。這樣客戶端就可以通過JWConnection對象任意的調用JDBC Connection接口的方法了。JWConnection在內部調用遠程服務器的Connection。比如當客戶端調用conn.createStatement()方法時(conn是一個JWConnection的引用),其內部會調用一個RemoteConnection.createConnection()方法,並返回一個遠程的Statement引用;JWConnectoin的createStatement方法會創建一個JWStatement對象;最後一個JWStatement對象會返回個客戶端,這個對象中包含的Statement的引用:
public Statement createStatement() throwsSQLException{try{IRemoteStatement remStmt =(IRemoteStatement) remoteConnection.createStatement();JWStatement localStmtInstance = new JWStatement(remStmt);return (Statement)localStmtInstance;}}
描述了客戶層和中間層中Connection和Statemennt類之間的關系。
Connection和Statement之間的關系
下面再讓我們來看看JWStatement類
JWStatement類
com.jw.clent.JWS