淺談標準SQL數據庫訪問界面—JDBC API
JDBC API定義了一系列Java類,用來表示數據庫連接、SQL語句、結果集、數據庫元數據等,能夠使Java編程人員發送SQL語句和處理返回結果。 JDBC API由一個驅動程序管理器實現對連接到不同數據庫的多個驅動程序的管理。JDBC驅動程序可以全部由Java語言編寫,也可以由本地化方法來實現與現有數據庫訪問接口的連接。
一、總體結構 Java應用程序通過JDBC API界面訪問JDBC管理器,JDBC管理器通過JDBC驅動程序API訪問不同的JDBC驅動程序,從而實現對不同數據庫的訪問。
1.JDBC API
JDBC API定義了一系列抽象Java界面,可以使應用程序員連接到指定的數據庫,執行SQL語句和處理返回結果。其功能結構如圖2所示。 @@I2;圖2 JDBC API主要功能結構@@ JDBC API中重要的界面有: java.sgl.DriverManager:完成驅動程序的裝載和建立新的數據庫連接。 java.sgl.Connection:表示對某一指定數據庫的連接。 java.sgl.Statement:管理在一指定數據庫連接上的SQL語句的執行。 java.sgl.ResultSet:訪問一指定語句的原始結果。 java.sgl.Statement:界面有兩個重要的子類型:ja-va.sgl.PreparedStatement (用于對預編譯的SQL語句的執行)和java.sgl.CallableStatement(用于對一個數據庫存儲過程的執行)。
2. JDBC驅動程序界面
數據庫驅動程序中必須實現在JDBC API中定義的抽象類,尤其是對java.sgl.Connection、java.sgl.Prepared-Statement、java.sgl.CallableStatement和java.sgl.Re-sultSet的實現。此外,每一個數據庫驅動程序必須提供一個類實現 java.sgl.Driver界面,用于通用的java.sgl.DriverManager類,使其在對一個指定的數據庫URL訪問時可以查找相應的驅動程序。 Sun Microsystems公司提供了一個JDBC對ODBC的連接橋,如圖1中 JDBC-ODBC橋接驅動程序所示。由于是建立在ODBC基礎之上,所以具有規模較小而效率高的特點。
3.用戶典型使用模式
(1)Applet模式 使用Java語言編制 Applet,作為 WWW文檔的一部分在Internet上發布,由瀏覽器對其下載,并運行。其中,可能會有部分Applet需要訪問數據庫,則可通過使用JDBC API實現,由于未信任的Applet不能訪問本地文件和對任意主機建立網絡連接,JDBC必須遵守標準Applet的安全模型,所以此種應用模式有諸多安全方面的限制。對信任的Applet,其安全模型類似于Java應用程序。
(2)應用程序模式 在應用程序中,Java代碼是信任的,因而可以讀寫本地文件和建立網絡連接。應用示意如圖4所示。 @@I4;圖4 應用程序應用模式@@ 此種應用模式非常適合intranet(內部網)應用。當然該模式也能夠通過Internet訪問數據庫。 二、JDBC API 1.JDBC界面定義 JDBC API包含java.sgl的界面和類。 java.sgl.CallableStatement:用于執行存儲的SQL過程的界面。 java.sgl.Connection: 一個連接表示與某一指定數據庫的一個會話。在該連接中可以執行SQL語句和處理返回結果。 java.sql.DataTruncation:當JDBC碰到意外數據截斷時,報告一個警告(讀數據時)或產生一個異常(寫數據時)。 java.sql.Date:是標準java.util.date的一個子集,只表示天數,而不包含時、分、秒。 java.sql.Driver:定義一個在每一個數據庫驅動程序中必須實現的驅動程序界面。 java.sql.DriverManager:提供對全局SQL狀態的訪問。 java.sql.DriverPropertyInto:提供高級程序員與驅動程序之間對連接特性信息進行交互的手段。 java.sql.NullData:當由getXXX或getObiect方法讀出一個SQL空值時,產生一個NullData警告。 java.sql.Numeric:是一個任意精度標量數值類,可用作表示SQL定點Numerlc和Decimal類型的數值。 java.sql.PreparedStatement:保存一個預編譯的SQL語句的對象,該對象可被高效地執行多次。 java.sql.ResultSet:結果集提供對執行一個SQL語句后產生的結果表的訪問。表中數據按行依次取出。為便于移植,建議對每一行數據從左至右按列讀出。 java.sql.SQLException:處理數據庫訪問時的出錯信息。 java.sql.SQLWarning:處理數據庫訪問時的警告信息。 java.sql.Statement:用作執行一條靜態的SQL語句并接收產生的結果。 java.sql.Time:用于表示標準java.util.date類的一個信息子集,僅表示時、分、秒。 java.sql.Timestamp:擴展標準java.util.date類,使其能夠表示SQL的時間戳,增加了一個以納秒為單位的時間域。 java.sql.Types:定義區分SQL類型的常量。類常量值與XOPEN中的值相同。 此外,JDBC API 還定義了JDBC元數據界面java.sql.DatabaseMetaData 和java.sql.ResultSetMetaData。 @@I5;圖5 界面之間的關系@@ 界面間的關系由圖5表示,其中箭頭表示函數,而線表示其它方法。
2.數據庫連接
(1)建立一個連接 用戶在訪問數據庫時,需要在JD-BC管理層由 java.sql.DriverManager.getConnection方法產生一個java.sql.Connection對象。該方法使用一個數據庫URL串作為參數。
(2)選擇合適的驅動程序 在數據庫URL中,可以指定驅動程序的名稱,也可以不指定。如果不指定驅動程序,則從Java特性"sql.drivers"所指出的驅動程序表中依次搜尋,使用***找到的可成功連接的驅動程序。
(3)數據庫URL 在連接時,由數據庫URL參數指定要連接的數據庫,此時可稱為JDBC URL,其格式為: jdbc:<子協議>:<子名稱> 如果是對網絡數據庫訪問,那么建議用戶使用標準URL作為子名稱的一部分。比如對數據資源名為fred訪問的URL可能是: jdbc:odbc:fred 或jdbc:dbnet://wombat:356/fred 子協議odbc表示對ODBC數據資源的訪問,其格式為: jdbc:odbc:<數據資源名>[;<屬性名>=<屬性值>]* ·連接參數:由java.util.Properties對象指出。建議大多數參數不要在此處給出,而在協議中指出。 ·支持多連接:一個應用程序可以使用一個或多個驅動程序建立與多個數據庫連接。 ·驅動程序的注冊:有兩種方法,一是在JDBC java.sql.DriverManager類初始化時查找"sql.drivers"特性,對每一個驅動程序自動注冊;二是由標準 Class.forName方法顯式加載一個驅動程序,參數為驅動程序名。
3.參數傳遞和結果接收
(1)查詢結果 執行一條查詢語句后,返回結果是可由java.sql.ResultSet對象訪問的行的集合。在該對象中提供了一系列"get" 方法,訪問當前的每一列,Result-Set.next方法可實現在結果集的行之間移動,可以使用列索引或列名指定相應的列。 ·查詢結果的數據轉換。 ResultSet.getXXX方法可以把SQL類型轉化為需要的Java類型。若指定一個非法的類型轉換時,則產生一個SQLException的異常。 ·空值判斷。先讀出某一列數據,然后使用Result-Set.wasNull方法,判斷返回結果是否是SQL"NULL"。 ·長數據的讀出。JDBC支持由getByte和getString 方法讀出任意長的LONGVARBINARY或LONGVAR-CHAR類型數據,也支持由方法GetBinaryStream、GetAsciiStream 和 GetUnicodeStream返回數據流來讀出數據。 ·支持用getResultSet、GetUpdateCount 和 Get-MoreResults方法分別返回一條結果、返回被修改的行數和返回多條結果。
(2)傳遞IN參數 java.sql.PreparedStatement界面提供了一系列setXXX方法向SQL語句傳遞參數,實現動態的SQL語句。 在傳遞參數時必須滿足數據類型一致的要求。因此必須預先調用類型轉換方法完成數據轉換,同時也提供了傳遞SQL空值和長數據給IN參數的方法。
(3)接收OUT參數 在調用一個存儲過程時,可用setXXX方法傳遞IN參數,使用OUT參數接收返回結果。在使用時必須先調用CallableStatement.register-OutParameter方法為每一個OUT參數進行類型注冊,然后執行該過程調用語句,***使用getXXX方法取出OUT參數的結果。 返回結果的數據類型是與用戶注冊的SQL類型相對應的Java類型。空值的處理步驟是,先讀出參數值,再用CallableStatement.was-Null方法判斷是否為空值。 不支持以流形式讀出OUT參數的機制。 接收時返回結果的順序優先于OUT參數。
(4)數據截斷 在某種條件下,有可能在讀或寫數據時出現數據截斷,如當由Connection.setMaxField-Size設置了一個域的***長度時,超過設置長度后的數據就被截斷。 在讀數據時,如出現數據截斷,則產生一條Data-Truncation 的 SQLWarning警告。在寫數據時,如發生數據截斷,則產生一個DataTruncation的SQLException異常。
4. SQL數據類型到Java類型的轉換 由于SQL數據類型與Java數據類型之間差異較大,可相互轉換的類型之間還是存在一些不一致的地方,因此JDBC提供了詳細的從SQL類型到Java類型的標準轉換表和從Java類型到SQL類型的標準轉換表。
三、進一步了解JDBC API 1.異步、線程和交易
(1)異步請求 某些數據庫API (比如ODBC) 提供了SQL語句異步執行的機制,這樣可使一個數據庫的操作在后臺運行的同時,前臺一邊等待一邊處理其它操作。 由于Java提供多線程機制,因此并不真正需要實現異步SQL語句的執行。當需要異步執行時,可通過創建一個新線程來實現數據庫操作。
(2)多線程 對java.sql的所有對象的操作是多線程安全的,并且當多個線程同時訪問一個對象時,也保證操作的正確性。盡管不同的驅動程序其并發執行程度可能不同,但開發人員可以假定為完全并發執行的。因為驅動程序若需要某種形式的同步操作,則一定會提供相應的實現機制。 另一個多線程的特殊應用是可以取消一個執行時間過長的語句操作。具體做法是啟動另一個線程調用Statement.cancel()方法
(3)交易 每一個新的JDBC連接都初始化為"自動提交"模式,即意味著每一條語句作為一個分開的交易來執行。 當需要把多條語句作為一個完整的交易來執行時,可以調用Connection.setAutoCommit(false)方法,取消自動提交。執行完一個交易后,調用Connection.Commit顯式完成提交,或調用Connection.rollback卷回整個交易操作。 當一個交易被提交或卷回后,關閉所有在此連接上的PreparedStatements、CallableStatements和ResultSets,只有簡單的Statements是打開狀態。
2.指針
JDBC支持簡單指針,這里說的指針是指SQL數據庫中的概念。應用程序可以用ResultSet.GetCursorName()方法,取得與當前Resultset相關聯的指針,利用該指針可以對當前行進行修改和刪除。 指針的有效期是到ResultSet或其父語句結束。
3.對SQL的擴充 JDBC全部支持SQL-2基本(Entry)級規范,部分支持SQL-2過渡(Transitional)級規范。對SQL-2基本級擴充有二點:一是支持DROP TABLE命令;二是選定的過渡級語義必須通過Escape語法來支持,以便一個驅動程序可以方便地掃描和翻譯成特定DBMS語法。
(1) SQL Escape語法 在存儲過程、標量函數、日期、時間、輸出連接等方面,JDBC支持與ODBC相同的DBMS無關的Escape轉義語法,格式為: {關鍵字……參數……}
(2)存儲過程 JDBC中激活一個存儲過程語法格式是: { call 過程名[參數1,參數2,…] } 或者是帶返回結果參數的過程: { ? = call 過程名[參數1,參數2,…] } (3)時間和時期文字量 JDBC支持這些文字量的ISO標準格式,用Escape轉義的語句表示時間和日期,如{ d 'yyyy-mm-dd'}或{ t 'nn:mm:ss'} 分別表示日期或時間。
(4)標量函數 JDBC支持標量值的數值、串、時間、日期、系統和轉換函數,如,{ fn concat ("Hot", "Java") }。
(5)輸出連接 語法格式為:{ oj outer-join } 其中outer-join形式為: table LEFT OUTER JOIN { table( outer-join} ON search-condition
4.動態數據庫訪問
盡管我們希望JDBC程序員在編程時能夠了解數據庫的模式,以便使用強類型的JDBC界面對數據庫進行訪問。但一個應用程序,有時需要動態得到數據庫模式,并以此信息完成相應的動態數據庫訪問。
(1)元數據信息 JDBC能夠對元數據進行訪問,比如行結果描述、語句參數、數據庫特性等。 Java.Sql.ResultSetMetaData類型提供了大量方法去獲得一個指定 Java.sql.ResultSet對象列的類型和特性。 Java.Sql.DatabaseMetaData界面提供一系列方法去獲得與某一數據庫相關聯的各種元數據,包含數據庫的過程、表、模式等和表中的列、列的訪問權、表的訪問權等信息。
(2)動態類型數據訪問 JDBC使用ResultSet.getObject、PreparedStatement.setObject和CallableStatement.getObject方法支持更一般的數據訪問。動態訪問時從SQL類型到Java對象類型的轉換表和從Java對象類型到SQL類型的轉換表在此就不加以列舉了。但上述三個方法中類型轉換的依據是這兩張表。
四、結束語
Java語言提供了訪問數據庫的API,這非常有助于其拓寬應用范圍。由于目前僅實現了一個基礎的API,所以希望開發人員以此為基礎,建立更高級的類和應用工具,同時,也希望諸多開發商提供多種數據庫驅動程序,以滿足編程人員訪問不同數據庫資源的需要。
【編輯推薦】



















