Java數(shù)據(jù)庫連接:JDBC應(yīng)用說明
|
■DriverManager 類 DriverManager 類是 JDBC 的管理層,作用于用戶和驅(qū)動(dòng)程序之間。它跟蹤可用的驅(qū)動(dòng)程序,并在數(shù)據(jù)庫和相應(yīng)驅(qū)動(dòng)程序之間建立連接。另外,DriverManager 類也處理諸如驅(qū)動(dòng)程序登錄時(shí)間限制及登錄和跟蹤消息的顯示等事務(wù)。 對于簡單的應(yīng)用程序,一般程序員需要在此類中直接使用的唯一方法是 DriverManager.getConnection。正如名稱所示,該方法將建立與數(shù)據(jù)庫的連接。JDBC 允許用戶調(diào)用 DriverManager 的方法 getDriver、getDrivers 和 registerDriver 及 Driver 的方法 connect。但多數(shù)情況下,讓 DriverManager 類管理建立連接的細(xì)節(jié)為上策。 ■跟蹤可用驅(qū)動(dòng)程序 DriverManager 類包含一列 Driver 類,它們已通過調(diào)用方法 DriverManager.registerDriver 對自己進(jìn)行了注冊。所有 Driver 類都必須包含有一個(gè)靜態(tài)部分。它創(chuàng)建該類的實(shí)例,然后在加載該實(shí)例時(shí) DriverManager 類進(jìn)行注冊。這樣,用戶正常情況下將不會(huì)直接調(diào)用 DriverManager.registerDriver;而是在加載驅(qū)動(dòng)程序時(shí)由驅(qū)動(dòng)程序自動(dòng)調(diào)用。加載 Driver 類,然后自動(dòng)在 DriverManager 中注冊的方式有兩種: 通過調(diào)用方法 Class.forName。這將顯式地加載驅(qū)動(dòng)程序類。由于這與外部設(shè)置無關(guān),因此推薦使用這種加載驅(qū)動(dòng)程序的方法。以下代碼加載類 acme.db.Driver: Class.forName("acme.db.Driver"); 如果將 acme.db.Driver 編寫為加載時(shí)創(chuàng)建實(shí)例,并調(diào)用以該實(shí)例為參數(shù)的 DriverManager.registerDriver(本該如此),則它在 DriverManager 的驅(qū)動(dòng)程序列表中,并可用于創(chuàng)建連接。 通過將驅(qū)動(dòng)程序添加到 java.lang.System 的屬性 jdbc.drivers 中。這是一個(gè)由 DriverManager 類加載的驅(qū)動(dòng)程序類名的列表,由冒號分隔:初始化 DriverManager 類時(shí),它搜索系統(tǒng)屬性 jdbc.drivers,如果用戶已輸入了一個(gè)或多個(gè)驅(qū)動(dòng)程序,則 DriverManager 類將試圖加載它們。以下代碼說明程序員如何在 ~/.hotjava/properties 中輸入三個(gè)驅(qū)動(dòng)程序類(啟動(dòng)時(shí),HotJava 將把它加載到系統(tǒng)屬性列表中): jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver; 對 DriverManager 方法的第一次調(diào)用將自動(dòng)加載這些驅(qū)動(dòng)程序類。 注意:加載驅(qū)動(dòng)程序的第二種方法需要持久的預(yù)設(shè)環(huán)境。如果對這一點(diǎn)不能保證,則調(diào)用方法 Class.forName 顯式地加載每個(gè)驅(qū)動(dòng)程序就顯得更為安全。這也是引入特定驅(qū)動(dòng)程序的方法,因?yàn)橐坏?DriverManager 類被初始化,它將不再檢查 jdbc.drivers 屬性列表。 在以上兩種情況中,新加載的 Driver 類都要通過調(diào)用 DriverManager.registerDriver 類進(jìn)行自我注冊。如上所述,加載類時(shí)將自動(dòng)執(zhí)行這一過程。 由于安全方面的原因,JDBC 管理層將跟蹤哪個(gè)類加載器提供哪個(gè)驅(qū)動(dòng)程序。這樣,當(dāng) DriverManager 類打開連接時(shí),它僅使用本地文件系統(tǒng)或與發(fā)出連接請求的代碼相同的類加載器提供的驅(qū)動(dòng)程序。 ■建立連接 加載 Driver 類并在 DriverManager 類中注冊后,它們即可用來與數(shù)據(jù)庫建立連接。當(dāng)調(diào)用 DriverManager.getConnection 方法發(fā)出連接請求時(shí),DriverManager 將檢查每個(gè)驅(qū)動(dòng)程序,查看它是否可以建立連接。 有時(shí)可能有多個(gè) JDBC 驅(qū)動(dòng)程序可以與給定的 URL 連接。例如,與給定遠(yuǎn)程數(shù)據(jù)庫連接時(shí),可以使用 JDBC-ODBC 橋驅(qū)動(dòng)程序、JDBC 到通用網(wǎng)絡(luò)協(xié)議驅(qū)動(dòng)程序或數(shù)據(jù)庫廠商提供的驅(qū)動(dòng)程序。在這種情況下,測試驅(qū)動(dòng)程序的順序至關(guān)重要,因?yàn)?DriverManager 將使用它所找到的第一個(gè)可以成功連接到給定 URL 的驅(qū)動(dòng)程序。 DriverManager 試圖按注冊的順序使用每個(gè)驅(qū)動(dòng)程序(jdbc.drivers 中列出的驅(qū)動(dòng)程序總是先注冊)。它將跳過代碼不可信任的驅(qū)動(dòng)程序,除非加載它們的源與試圖打開連接的代碼的源相同。它通過輪流在每個(gè)驅(qū)動(dòng)程序上調(diào)用方法 Driver.connect,并向它們傳遞用戶開始傳遞給方法 DriverManager.getConnection 的 URL 來對驅(qū)動(dòng)程序進(jìn)行測試,然后連接第一個(gè)認(rèn)出該 URL 的驅(qū)動(dòng)程序。這種方法初看起來效率不高,但由于不可能同時(shí)加載數(shù)十個(gè)驅(qū)動(dòng)程序,因此每次連接實(shí)際只需幾個(gè)過程調(diào)用和字符串比較。以下代碼是通常情況下用驅(qū) 動(dòng)程序(例如 JDBC-ODBC 橋驅(qū)動(dòng)程序)建立連接所需所有步驟的示例: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加載驅(qū)動(dòng)程序 String url = "jdbc:odbc:fred"; DriverManager.getConnection(url, "userID", "passwd"); 8.語句 ■Statement 對象概述 Statement 對象用于將 SQL 語句發(fā)送到數(shù)據(jù)庫中。實(shí)際上有三種 Statement 對象,它們都作為在給定連接上執(zhí)行 SQL 語句的包容器:Statement、PreparedStatement(它從 Statement 繼承而來)和 CallableStatement(它從 PreparedStatement 繼承而來)。它們都專用于發(fā)送特定類型的 SQL 語句: Statement 對象用于執(zhí)行不帶參數(shù)的簡單 SQL 語句;PreparedStatement 對象用于執(zhí)行帶或不帶 IN 參數(shù)的預(yù)編譯 SQL 語句;CallableStatement 對象用于執(zhí)行對數(shù)據(jù)庫已存儲過程的調(diào)用。 Statement 接口提供了執(zhí)行語句和獲取結(jié)果的基本方法。PreparedStatement 接口添加了處理 IN 參數(shù)的方法;而 CallableStatement 添加了處理 OUT 參數(shù)的方法。 ■創(chuàng)建 Statement 對象 建立了到特定數(shù)據(jù)庫的連接之后,就可用該連接發(fā)送 SQL 語句。Statement 對象用 Connection 的方法 createStatement 創(chuàng)建,如下列代碼段中所示: Connection con = DriverManager.getConnection(url, "sunny", ""); Statement stmt = con.createStatement(); 為了執(zhí)行 Statement 對象,被發(fā)送到數(shù)據(jù)庫的 SQL 語句將被作為參數(shù)提供給 Statement 的方法: ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2"); ■使用 Statement 對象執(zhí)行語句 Statement 接口提供了三種執(zhí)行 SQL 語句的方法:executeQuery、executeUpdate 和 execute。使用哪一個(gè)方法由 SQL 語句所產(chǎn)生的內(nèi)容決定。 方法 executeQuery 用于產(chǎn)生單個(gè)結(jié)果集的語句,例如 SELECT 語句。 方法 executeUpdate 用于執(zhí)行 INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(數(shù)據(jù)定義語言)語句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 語句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一個(gè)整數(shù),指示受影響的行數(shù)(即更新計(jì)數(shù))。對于 CREATE TABLE 或 DROP TABLE 等不操作行的語句,executeUpdate 的返回值總為零。 方法 execute 用于執(zhí)行返回多個(gè)結(jié)果集、多個(gè)更新計(jì)數(shù)或二者組合的語句。 執(zhí)行語句的所有方法都將關(guān)閉所調(diào)用的 Statement 對象的當(dāng)前打開結(jié)果集(如果存在)。這意味著在重新執(zhí)行 Statement 對象之前,需要完成對當(dāng)前 ResultSet 對象的處理。 應(yīng)注意,繼承了 Statement 接口中所有方法的 PreparedStatement 接口都有自己的 executeQuery、executeUpdate 和 execute 方法。Statement 對象本身不包含 SQL 語句,因而必須給 Statement.execute 方法提供 SQL 語句作為參數(shù)。PreparedStatement 對象并不將 SQL 語句作為參數(shù)提供給這些方法,因?yàn)樗鼈円呀?jīng)包含預(yù)編譯 SQL 語句。CallableStatement 對象繼承這些方法的 PreparedStatement 形式。對于這些方法的 PreparedStatement 或 CallableStatement 版本,使用查詢參數(shù)將拋出 SQLException。 ■語句完成 當(dāng)連接處于自動(dòng)提交模式時(shí),其中所執(zhí) 行的語句在完成時(shí)將自動(dòng)提交或還原。語句在已執(zhí)行且所有結(jié)果返回時(shí),即認(rèn)為已完成。對于返回一個(gè)結(jié)果集的 executeQuery 方法,在檢索完 ResultSet 對象的所有行時(shí)該語句完成。對于方法 executeUpdate,當(dāng)它執(zhí)行時(shí)語句即完成。但在少數(shù)調(diào)用方法 execute 的情況中,在檢索所有結(jié)果集或它生成的更新計(jì)數(shù)之后語句才完成。 有些 DBMS 將已存儲過程中的每條語句視為獨(dú)立的語句;而另外一些則將整個(gè)過程視為一個(gè)復(fù)合語句。在啟用自動(dòng)提交時(shí),這種差別就變得非常重要,因?yàn)樗绊懯裁磿r(shí)候調(diào)用 commit 方法。在前一種情況中,每條語句單獨(dú)提交;在后一種情況中,所有語句同時(shí)提交。 ■關(guān)閉 Statement 對象 Statement 對象將由 Java 垃圾收集程序自動(dòng)關(guān)閉。而作為一種好的編程風(fēng)格,應(yīng)在不需要 Statement 對象時(shí)顯式地關(guān)閉它們。這將立即釋放 DBMS 資源,有助于避免潛在的內(nèi)存問題。 9.結(jié)果設(shè)置 ■概述 ResultSet 包含符合 SQL 語句中條件的所有行,并且它通過一套 get 方法(這些 get 方法可以訪問當(dāng)前行中的不同列)提供了對這些行中數(shù)據(jù)的訪問。ResultSet.next 方法用于移動(dòng)到 ResultSet 中的下一行,使下一行成為當(dāng)前行。 ■行和光標(biāo) ResultSet 維護(hù)指向其當(dāng)前數(shù)據(jù)行的光標(biāo)。每調(diào)用一次 next 方法,光標(biāo)向下移動(dòng)一行。最初它位于第一行之前,因此第一次調(diào)用 next 將把光標(biāo)置于第一行上,使它成為當(dāng)前行。隨著每次調(diào)用 next 導(dǎo)致光標(biāo)向下移動(dòng)一行,按照從上至下的次序獲取 ResultSet 行。在 ResultSet 對象或其父輩 Statement 對象關(guān)閉之前,光標(biāo)一直保持有效。在 SQL 中,結(jié)果表的光標(biāo)是有名字的。如果數(shù)據(jù)庫允許定位更新或定位刪除,則需要將光標(biāo)的名字作為參數(shù)提供給更新或刪除命令。可通過調(diào)用方法 getCursorName 獲得光標(biāo)名。 注意:不是所有 DBMS支持定位更新和刪除??墒褂? DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法來檢查特定連接是否支持這些操作。當(dāng)支持這些操作時(shí),DBMS/驅(qū)動(dòng)程序必須確保適當(dāng)鎖定選定行,以使定位更新不會(huì)導(dǎo)致更新異?;蚱渌l(fā)問題。 ■列 方法 getXXX 提供了獲取當(dāng)前行中某列值的途徑。在每一行內(nèi),可按任何次序獲取列值。但為了保證可移植性,應(yīng)該從左至右獲取列值,并且一次性地讀取列值。列名或列號可用 于標(biāo)識要從中獲取數(shù)據(jù)的列。例如,如果 ResultSet 對象 rs 的第二列名為“title”,并將值存儲為字符串,則下列任一代碼將獲取存儲在該列中的值: String s = rs.getString("title"); String s = rs.getString(2); 注意列是從左至右編號的,并且從列 1 開始。同時(shí),用作 getXXX 方法的輸入的列名不區(qū)分大小寫。 提供使用列名這個(gè)選項(xiàng)的目的是為了讓在查詢中指定列名的用戶可使用相同的名字作為 getXXX 方法的參數(shù)。另一方面,如果 select 語句未指定列名(例如在“select * from table1”中或列是導(dǎo)出的時(shí)),則應(yīng)該使用列號。這些情況下,用戶將無法確切知道列名。 有些情況下,SQL 查詢返回的結(jié)果集中可能有多個(gè)列具有相同的名字。如果列名用作 getXXX 方法的參數(shù),則 getXXX 將返回第一個(gè)匹配列名的值。因而,如果多個(gè)列具有相同的名字,則需要使用列索引來確保檢索了正確的列值。這時(shí),使用列號效率要稍微高一些。 ■數(shù)據(jù)類型和轉(zhuǎn)換 對于 getXXX 方法,JDBC 驅(qū)動(dòng)程序試圖將基本數(shù)據(jù)轉(zhuǎn)換成指定 Java 類型,然后返回適合的 Java 值。例如,如果 getXXX 方法為 getString,而基本數(shù)據(jù)庫中數(shù)據(jù)類型為 VARCHAR,則 JDBC 驅(qū)動(dòng)程序?qū)?VARCHAR 轉(zhuǎn)換成 Java String。getString 的返回值將為 Java String 對象??墒褂?ResultSet.getXXX 方法獲取常見的 JDBC 數(shù)據(jù)類型。 準(zhǔn)備語句 ■概述 該 PreparedStatement 接口繼承 Statement,并與之在兩方面有所不同: PreparedStatement 實(shí)例包含已編譯的 SQL 語句。這就是使語句“準(zhǔn)備好”。 包含于 PreparedStatement 對象中的 SQL 語句可具有一個(gè)或多個(gè) IN 參數(shù)。IN 參數(shù)的值在 SQL 語句創(chuàng)建時(shí)未被指定。相反的,該語句為每個(gè) IN 參數(shù)保留一個(gè)問號(“?”)作為占位符。每個(gè)問號的值必須在該語句執(zhí)行之前,通過適當(dāng)?shù)? setXXX 方法來提供。 由于 PreparedStatement 對象已預(yù)編譯過,所以其執(zhí)行速度要快于 Statement 對象。因此,多次執(zhí)行的 SQL 語句經(jīng)常創(chuàng)建為 PreparedStatement 對象,以提高效率。 作為 Statement 的子類,PreparedStatement 繼承了 Statement 的所有功能。另外它還添加了一整套方法,用于設(shè)置發(fā)送給數(shù)據(jù)庫以取代 IN 參數(shù)占位符的值。同時(shí),三種方法 execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要參數(shù)。這些方法的 Statement 形式(接受 SQL 語句參數(shù)的形式)不應(yīng)該用于 PreparedStatement 對象。 ■創(chuàng)建 PreparedStatement 對象 以下的代碼段(其中 con 是 Connection 對象)創(chuàng)建包含帶兩個(gè) IN 參數(shù)占位符的 SQL 語句的 PreparedStatement 對象: PreparedStatement pstmt = con.prepareStatement( "UPDATE table4 SET m = ? WHERE x = ?"); pstmt 對象包含語句 "UPDATE table4 SET m = ? WHERE x = ?",它已發(fā)送給 DBMS,并為執(zhí)行作好了準(zhǔn)備。 ■傳遞 IN 參數(shù) 在執(zhí)行 PreparedStatement 對象之前,必須設(shè)置每個(gè) ? 參數(shù)的值。這可通過調(diào)用 setXXX 方法來完成,其中 XXX 是與該參數(shù)相應(yīng)的類型。例如,如果參數(shù)具有 Java 類型 long,則使用的方法就是 setLong。setXXX 方法的第一個(gè)參數(shù)是要設(shè)置的參數(shù)的序數(shù)位置,第二個(gè)參數(shù)是設(shè)置給該參數(shù)的值。例如,以下代碼將第一個(gè)參數(shù)設(shè)為 123456789,第二個(gè)參數(shù)設(shè)為 100000000: pstmt.setLong(1, 123456789); pstmt.setLong(2, 100000000); 一旦設(shè)置了給定語句的參數(shù)值,就可用它多次執(zhí)行該語句,直到調(diào)用 clearParameters 方法清除它為止。 在連接的缺省模式下(啟用自動(dòng)提交),當(dāng)語句完成時(shí)將自動(dòng)提交或還原該語句。 如果基本數(shù)據(jù)庫和驅(qū)動(dòng)程序在語句提交之后仍保持這些語句的打開狀態(tài),則同一個(gè) PreparedStatement 可執(zhí)行多次。如果這一點(diǎn)不成立,那么試圖通過使用 PreparedStatement 對象代替 Statement 對象來提高性能是沒有意義的。 利用 pstmt(前面創(chuàng)建的 PreparedStatement 對象),以下代碼例示了如何設(shè)置兩個(gè)參數(shù)占位符的值并執(zhí)行 pstmt 10 次。如上所述,為做到這一點(diǎn),數(shù)據(jù)庫不能關(guān)閉 pstmt。在該示例中,第一個(gè)參數(shù)被設(shè)置為 "Hi"并保持為常數(shù)。在 for 循環(huán)中,每次都將第二個(gè)參數(shù)設(shè)置為不同的值:從 0 開始,到 9 結(jié)束。 pstmt.setString(1, "Hi"); for (int i = 0; i < 10; i++) { pstmt.setInt(2, i); int rowCount = pstmt.executeUpdate(); } ■IN 參數(shù)中數(shù)據(jù)類型的一致性 setXXX 方法中的 XXX 是 Java 類型。它是一種隱含的 JDBC 類型(一般 SQL 類型),因?yàn)轵?qū)動(dòng)程序?qū)?Java 類型映射為相應(yīng)的 JDBC 類型(遵循該 JDBC Guide中§8.6.2 “映射 Java 和 JDBC 類型”表中所指定的映射),并將該 JDBC 類型發(fā)送給數(shù)據(jù)庫。例如,以下代碼段將 PreparedStatement 對象 pstmt 的第二個(gè)參數(shù)設(shè)置為 44,Java 類型為 short: pstmt.setShort(2, 44); 驅(qū)動(dòng)程序?qū)?44 作為 JDBC SMALLINT 發(fā)送給數(shù)據(jù)庫,它是 Java short 類型的標(biāo)準(zhǔn)映射。 程序員的責(zé)任是確保將每個(gè) IN 參數(shù)的 Java 類型映射為與數(shù)據(jù)庫所需的 JDBC 數(shù)據(jù)類型兼容的 JDBC 類型。不妨考慮數(shù)據(jù)庫需要 JDBC SMALLINT 的情況。如果使用方法 setByte ,則驅(qū)動(dòng)程序?qū)?JDBC TINYINT 發(fā)送給數(shù)據(jù)庫。這是可行的,因?yàn)樵S多數(shù)據(jù)庫可從一種相關(guān)的類型轉(zhuǎn)換為另一種類型,并且通常 TINYINT 可用于 SMALLINT 適用的任何地方。然而,對于要適用于盡可能多的數(shù)據(jù)庫的應(yīng)用程序,最好使用與數(shù)據(jù)庫所需的確切的 JDBC 類型相應(yīng)的 Java 類型。如果所需的 JDBC 類型是 SMALLINT,則使用 setShort 代替 setByte 將使應(yīng)用程序的可移植性更好。 ■ JDBC URL JDBC URL 提供了一種標(biāo)識數(shù)據(jù)庫的方法,可以使相應(yīng)的驅(qū)動(dòng)程序能識別該數(shù)據(jù)庫并與之建立連接。實(shí)際上,驅(qū)動(dòng)程序編程員將決定用什么 JDBC URL 來標(biāo)識特定的驅(qū)動(dòng)程序。用戶不必關(guān)心如何來形成 JDBC URL;他們只須使用與所用的驅(qū)動(dòng)程序一起提供的 URL 即可。JDBC 的作用是提供某些約定,驅(qū)動(dòng)程序編程員在構(gòu)造他們的 JDBC URL 時(shí)應(yīng)該遵循這些約定。 (1) 由于 JDBC URL 要與各種不同的驅(qū)動(dòng)程序一起使用,因此這些約定應(yīng)非常靈活。它們應(yīng)允許不同的驅(qū)動(dòng)程序使用不同的方案來命名數(shù)據(jù)庫。例如, odbc 子協(xié)議允許(但并不是要求) URL 含有屬性值。 (2) JDBC URL 應(yīng)允許驅(qū)動(dòng)程序編程員將一切所需的信息編入其中。這樣就可以讓要與給定數(shù)據(jù)庫對話的 applet 打開數(shù)據(jù)庫連接,而無須要求用戶去做任何系統(tǒng)管理工作。 (3) JDBC URL 應(yīng)允許某種程度的間接性。也就是說,JDBC URL 可指向邏輯主機(jī)或數(shù)據(jù)庫名,而這種邏輯主機(jī)或數(shù)據(jù)庫名將由網(wǎng)絡(luò)命名系統(tǒng)動(dòng)態(tài)地轉(zhuǎn)換為實(shí)際的名稱。這可以使系統(tǒng)管理員不必將特定主機(jī)聲明為 JDBC 名稱的一部份。網(wǎng)絡(luò)命名服務(wù)(例如 DNS、 NIS 和 DCE )有多種,而對于使用哪種命名服務(wù)并無限制。 JDBC URL 的標(biāo)準(zhǔn)語法如下所示。 它由三部分組成,各部分間用冒號分隔:jdbc:< 子協(xié)議 >:< 子名稱 > JDBC URL 的三個(gè)部分可分解如下: jdbc ─ 協(xié)議。JDBC URL 中的協(xié)議總是 jdbc。 <子協(xié)議> ─ 驅(qū)動(dòng)程序名或數(shù)據(jù)庫連接機(jī)制(這種機(jī)制可由一個(gè)或多個(gè)驅(qū)動(dòng)程序支持)的名稱。子協(xié)議名的典型示例是 "odbc",該名稱是為用于指定 ODBC 風(fēng)格的數(shù)據(jù)資源名稱的 URL 專門保留的。例如,為了通過 JDBC-ODBC 橋來訪問某個(gè)數(shù)據(jù)庫,可以用如下所示的 URL: jdbc:odbc:fred 本例中,子協(xié)議為 "odbc",子名稱 "fred" 是本地 ODBC 數(shù)據(jù)資源。 如果要用網(wǎng)絡(luò)命名服務(wù)(這樣 JDBC URL 中的數(shù)據(jù)庫名稱不必是實(shí)際名稱),則命名服務(wù)可以作為子協(xié)議。例如,可用如下所示的 URL : jdbc:dcenaming:accounts-payable 本例中,該 URL 指定了本地 DCE 命名服務(wù)應(yīng)該將 數(shù)據(jù)庫名稱 "accounts-payable" 解析為更為具體的 可用于連接真實(shí)數(shù)據(jù)庫的名稱。 <子名稱> ─ 一種標(biāo)識數(shù)據(jù)庫的方法。子名稱可以依不同的子協(xié)議而變化。它還可以有子名稱的子名稱(含有驅(qū)動(dòng)程序編程員所選的任何內(nèi)部語法)。使用子名稱的目的是為定位 數(shù)據(jù)庫提供足夠的信息。前例中,因?yàn)?ODBC 將提供其余部份的信息,因此用 "fred" 就已足夠。然而,位于遠(yuǎn)程服務(wù)器上的數(shù)據(jù)庫需要更多的信息。例如,如果數(shù)據(jù)庫是通過 Internet 來訪問的,則在 JDBC URL 中應(yīng)將網(wǎng)絡(luò)地址作為子名稱的一部份包括進(jìn)去,且必須遵循如下所示的標(biāo)準(zhǔn) URL 命名約定: //主機(jī)名:端口/子協(xié)議 假設(shè) "dbnet" 是個(gè)用于將某個(gè)主機(jī)連接到 Internet 上的協(xié)議,則 JDBC URL 類似: jdbc:dbnet://wombat:356/fred ■ "odbc" 子協(xié)議 子協(xié)議 odbc 是一種特殊情況。它是為用于指定 ODBC 風(fēng)格的數(shù)據(jù)資源名稱的 URL 而保留的,并具有下列特性:允許在子名稱(數(shù)據(jù)資源名稱)后面指定任意多個(gè)屬性值。odbc 子協(xié)議的完整語法為: jdbc:odbc:< 數(shù)據(jù)資源名稱 >[;< 屬性名 >=< 屬性值 >]* 因此,以下都是合法的 jdbc:odbc 名稱: jdbc:odbc:qeor7 jdbc:odbc:wombat jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER jdbc:odbc:qeora;UID=kgh;PWD=fooey ■注冊子協(xié)議 驅(qū)動(dòng)程序編程員可保留某個(gè)名稱以將之用作 JDBC URL 的子協(xié)議名。當(dāng) DriverManager 類將此名稱加到已注冊的驅(qū)動(dòng)程序清單中時(shí),為之保留該名稱的驅(qū)動(dòng)程序應(yīng)能識別該名稱并與它所標(biāo)識的數(shù)據(jù)庫建立連接。例如,odbc 是為 JDBC- ODBC 橋而保留的。示例之二,假設(shè)有個(gè) Miracle 公司,它可能會(huì)將 "miracle" 注冊為連接到其 Miracle DBMS 上的 JDBC 驅(qū)動(dòng)程序的子協(xié)議,從而使其他人都無法使用這個(gè)名稱。 |