posts - 20,  comments - 7,  trackbacks - 0

          JDBC 提供三種類型的語句對象: Statement PreparedStatement CallableStatement

          其中 PreparedStatement Statement 的子類, CallableStatement PreparedStatement 的子類。每一種語句對象用來運(yùn)行特定類型的 SQL 語句。

          Statement 對象用來運(yùn)行簡單類型的 SQL 語句,語句中無需指定參數(shù)。

          PreparedStatement 對象用來運(yùn)行包含(或不包含) IN 類型參數(shù)的預(yù)編譯 SQL 語句。

          CallableStatement 對象用來調(diào)用數(shù)據(jù)庫存儲過程。

          ?

          ?

          Statement

          1. 概述

          Statement 對象用于將 SQL 語句發(fā)送到數(shù)據(jù)庫服務(wù)器。

          ?

          2. 創(chuàng)建 Statement 對象

          建立連接后, Statement 對象用 Connection 對象的 createStatement 方法創(chuàng)建,以下代碼創(chuàng)建 Statement 對象:

          Connection con = DriverManager.getConnection(url, SYSDBA, SYSDBA);

          Statement stmt = con.createStatement();

          ?

          3. 使用 Statement 對象執(zhí)行語句

          Statement 接口提供了三種執(zhí)行 SQL 語句的方法: executeQuery executeUpdate execute

          ?

          方法 executeQuery 用于產(chǎn)生單個結(jié)果集的語句,例如 SELECT 語句。

          ?

          方法 executeUpdate 用于執(zhí)行 INSERT UPDATE DELETE 語句以及 SQL DDL 語句,如 CREATE TABLE DROP TABLE INSERT UPDATE DELETE 語句的效果是修改表中零行或多行中的一列或多列。 executeUpdate 的返回值是一個整數(shù),表示受影響的行數(shù)。對于 CREATE TABLE DROP TABLE DDL 語句, executeUpdate 的返回值總為零。

          ?

          方法 execute 用于執(zhí)行返回多個結(jié)果集、多個更新元組數(shù)或二者組合的語句。

          ?

          執(zhí)行語句的三種方法都將關(guān)閉所調(diào)用的 Statement 對象的當(dāng)前打開結(jié)果集(如果存在)。這意味著在重新執(zhí)行 Statement 對象之前,需要完成對當(dāng)前 ResultSet 對象的處理。

          ?

          4. 關(guān)閉 Statement 對象

          Statement 對象可由 Java 垃圾收集程序自動關(guān)閉。但作為一種好的編程風(fēng)格,應(yīng)在不需要 Statement 對象時顯式地關(guān)閉它們。這將立即釋放數(shù)據(jù)庫服務(wù)器資源,有助于避免潛在的內(nèi)存問題。

          ?

          ?

          ?

          PreparedStatement

          1. 概述

          PreparedStatement 繼承 Statement ,并與之在兩方面有所不同:

          PreparedStatement 對象包含已編譯的 SQL 語句,語句已經(jīng) 準(zhǔn)備好

          包含于 PreparedStatement 對象中的 SQL 語句可具有一個或多個 IN 參數(shù)。 IN 參數(shù)的值在 SQL 語句創(chuàng)建時未被指定。相反,該語句為每個 IN 參數(shù)保留一個問號( )作為占位符。每個問號所對應(yīng)的值必須在該語句執(zhí)行之前,通過適當(dāng)?shù)?/span> setXXX 方法來提供。

          由于 PreparedStatement 對象已預(yù)編譯過,所以其執(zhí)行速度要快于 Statement 對象。因此,需要多次重復(fù)執(zhí)行的 SQL 語句經(jīng)常創(chuàng)建為 PreparedStatement 對象,以提高效率。

          ?

          作為 Statement 的子類, PreparedStatement 繼承了 Statement 的所有功能。另外它還添加了一整套方法,用于設(shè)置發(fā)送給數(shù)據(jù)庫以取代 IN 參數(shù)占位符的值。同時,三種方法 execute executeQuery executeUpdate 能執(zhí)行設(shè)置好參數(shù)的語句對象。

          ?

          2. 創(chuàng)建 PreparedStatement 對象

          以下的代碼段(其中 con Connection 對象)創(chuàng)建一個 PreparedStatement 對象:

          PreparedStatement pstmt = con.prepareStatement( UPDATE 廠商登記 SET 廠商名 = ? WHERE 廠商編號 = ?);

          對象 pstmt 包含語句 UPDATE 廠商登記 SET 廠商名 = ? WHERE 廠商編號 = ? ,該語句帶兩個 IN 參數(shù)占位符,它已發(fā)送給數(shù)據(jù)庫,并由服務(wù)器為其執(zhí)行作好了準(zhǔn)備。

          ?

          3. 傳遞 IN 參數(shù)

          在執(zhí)行 PreparedStatement 對象之前,必須設(shè)置每個 ? 參數(shù)的值。這可通過調(diào)用 setXXX 方法來完成,其中 XXX 是與該參數(shù)相應(yīng)的類型。例如,如果參數(shù)具有 Java 類型 String ,則使用的方法就是 setString 。對于不同類型的參數(shù),一般都會有一個推薦的設(shè)置方法和多個可行的設(shè)置方法。 setXXX 方法的第一個參數(shù)是要設(shè)置的參數(shù)的序號(從 1 算起),第二個參數(shù)是設(shè)置給該參數(shù)的值。譬如,以下代碼將第一個參數(shù)設(shè)為 中華電視機(jī)廠 ,第二個參數(shù)設(shè)為 “B0A01”

          pstmt.setString(1, 中華電視機(jī)廠 );

          pstmt.setString(2, B0A01);

          每當(dāng)設(shè)置了給定語句的參數(shù)值,就可執(zhí)行該語句。設(shè)置一組新的參數(shù)值之前,應(yīng)先調(diào)用 clearParameters 方法清除原先設(shè)置的參數(shù)值。

          ?

          4. 使用 setObject 方法 : 可顯式地將輸入?yún)?shù)轉(zhuǎn)換為特定的 JDBC 類型。

          該方法可以接受三個參數(shù),其中第三個參數(shù)用來指定目標(biāo) JDBC 類型。將 Java Object 發(fā)送給數(shù)據(jù)庫之前,驅(qū)動程序?qū)阉D(zhuǎn)換為指定的 JDBC 類型。

          如果沒有指定 JDBC 類型,驅(qū)動程序就會將 Java Object 映射到其缺省的 JDBC 類型,然后將它發(fā)送到數(shù)據(jù)庫。這與常規(guī)的 setXXX 方法類似。在這兩種情況下,驅(qū)動程序在將值發(fā)送到數(shù)據(jù)庫之前,會將該值的 Java 類型映射為適當(dāng)?shù)?/span> JDBC 類型。

          二者的差別在于 setXXX 方法使用從 Java 類型到 JDBC 類型的標(biāo)準(zhǔn)映射,而 setObject 方法使用從 Java Object 類型到 JDBC 類型的映射。

          ?

          方法 setObject 允許接受所有 Java 對象,這使應(yīng)用程序更為通用,并可在運(yùn)行時接受參數(shù)的輸入。這樣,如果用戶在編輯應(yīng)用程序時不能確定輸入類型,可以通過使用 setObject ,對應(yīng)用程序賦予可接受的 Java 對象,然后由 JDBC 驅(qū)動程序自動將其轉(zhuǎn)換成數(shù)據(jù)庫所需的 JDBC 類型。但如果用戶已經(jīng)清楚輸入類型,使用相應(yīng)的 setXXX 方法是值得推薦的,可以提高效率。

          ?

          5. JDBC NULL 作為 IN 參數(shù)發(fā)送

          setNull 方法允許程序員將 JDBC NULL 值作為 IN 參數(shù)發(fā)送給數(shù)據(jù)庫。在這種情況下,可以把參數(shù)的目標(biāo) JDBC 類型指定為任意值,同時參數(shù)的目標(biāo)精度也不再起作用。

          ?

          6. 發(fā)送大的 IN 參數(shù)

          setBytes setString 方法能夠發(fā)送無限量的數(shù)據(jù)。但是,內(nèi)存要足夠容納相關(guān)數(shù)據(jù)。有時程序員更喜歡用較小的塊傳遞大型的數(shù)據(jù),這可通過將 IN 參數(shù)設(shè)置為 Java 輸入流來完成。當(dāng)語句執(zhí)行時, JDBC 驅(qū)動程序?qū)⒅貜?fù)調(diào)用該輸入流,讀取其內(nèi)容并將它們當(dāng)作實(shí)際參數(shù)數(shù)據(jù)傳輸。

          JDBC 提供了四種將 IN 參數(shù)設(shè)置為輸入流的方法: setBinaryStream 用于字節(jié)流, setAsciiStream 用于 ASCII 字符流, setUnicodeStream 用于 Unicode 字符流,從 JDK1.2 起,輸入字符流的新方法為 setCharacterStream ,而 setAsciiStream setUnicodeStream 已經(jīng)很少用。

          ?

          7. 獲得參數(shù)元數(shù)據(jù)

          JDBC 3.0 實(shí)現(xiàn)了 getParameterMetaData() 方法,通過這個方法可以獲得有關(guān) IN 參數(shù)的各種屬性信息,比如類型、精度、刻度等信息,類似于結(jié)果集元數(shù)據(jù)的內(nèi)容。通過這些信息,用戶可以更準(zhǔn)確地設(shè)置 IN 參數(shù)的值。 `

          在下面的代碼中涉及到了這種方法:

          PreparedStatement pstmt = conn.prepareStatement(SELECT * FROM BOOKLIST “ + “WHERE ISBN = ? );

          ...

          // 獲得參數(shù)元數(shù)據(jù)對象

          ParameterMetaData pmd = pstmt.getParameterMetaData();

          // 獲得參數(shù)的個數(shù)

          int paramCount = pstmt.getParameterCount();

          // 獲得第一參數(shù)的類型

          int colType = pmd.getParameterType(1);

          8. 自定義方法列表

          為了實(shí)現(xiàn)對達(dá)夢數(shù)據(jù)庫所提供的時間間隔類型和帶納秒的時間類型的支持,在實(shí)現(xiàn) PreparedStatement 接口的過程中,增加了一些自定義的擴(kuò)展方法。用戶將獲得的 PreparedStatement 對象反溯成 DmdbPreparedStatment 類型就可以訪問這些方法。

          ?

          ?

          ?

          CallableStatement

          1. 概述

          CallableStatement 用來運(yùn)行 SQL 存儲過程。存儲過程是數(shù)據(jù)庫中已經(jīng)存在的 SQL 語句,它通過名字調(diào)用。

          CallableStatement PreparedStatement 的子類。 CallableStatement 中定義的方法用于處理 OUT 參數(shù)或 INOUT 參數(shù)的輸出部分:注冊 OUT 參數(shù)的 JDBC 類型(一般 SQL 類型)、從這些參數(shù)中檢索結(jié)果,或者檢查所返回的值是否為 JDBC NULL

          ?

          2. 創(chuàng)建 CallableStatement 對象

          CallableStatement 對象是用 Connection.prepareCall 創(chuàng)建的。

          以下代碼創(chuàng)建 CallableStatement 對象,其中含有對存儲過程 p1 的調(diào)用, con 為連接對象:

          CallableStatement cstmt = con.prepareCall(call p1(?, ?));

          其中 ? 占位符為 IN OUT 還是 INOUT 參數(shù),取決于存儲過程 p1

          ?

          3. IN OUT 參數(shù)

          IN 參數(shù)傳給 CallableStatement 對象是通過 setXXX 方法完成的。該方法繼承自 PreparedStatement 。所傳入?yún)?shù)的類型決定了所用的 setXXX 方法(例如,用 setString 來傳入 String 值等)。

          如果存儲過程返回 OUT 參數(shù),則在執(zhí)行 CallableStatement 對象之前必須先注冊每個 OUT 參數(shù)的 JDBC 類型,有的參數(shù)還要同時提供刻度。注冊 JDBC 類型是用 registerOutParameter 方法來完成的。語句執(zhí)行完后, CallableStatement getXXX 方法將取回參數(shù)值。其中 XXX 是為各參數(shù)所注冊的 JDBC 類型所對應(yīng)的 Java 類型。換言之, registerOutParameter 使用的是 JDBC 類型(因此它與數(shù)據(jù)庫返回的 JDBC 類型匹配),而 getXXX 將之轉(zhuǎn)換為 Java 類型。

          設(shè)存儲過程 p1 的定義如下:

          CREATE OR REPLACE PROCEDURE p1( a1 IN CHAR(5), a2 OUT CHAR(20)) AS

          DECLARE CUR1 CURSOR FOR

          SELECT 廠商名

          FROM 廠商登記

          WHERE 廠商編號 = a1;

          BEGIN

          OPEN CUR1;

          FETCH CUR1 INTO a2;

          END;

          以下代碼先注冊 OUT 參數(shù),執(zhí)行由 cstmt 所調(diào)用的存儲過程,然后檢索通過 OUT 參數(shù)返回的值。方法 getString OUT 參數(shù)中取出字符串:

          CallableStatement cstmt = con.prepareCall(call p1(?, ?));

          cstmt.setString(1, B0A05);

          cstmt.registerOutParameter(2, java.sql.Types.VARCHAR);

          cstmt.executeUpdate();

          String x = cstmt.getString(2);

          ?

          4. INOUT 參數(shù)

          如果參數(shù)為既接受輸入又接受輸出的參數(shù)類型( INOUT 參數(shù)),那么除了調(diào)用 registerOutParameter 方法外,還要調(diào)用對應(yīng)的 setXXX 方法(繼承自 PreparedStatement )。 setXXX 方法將參數(shù)值設(shè)置為輸入?yún)?shù),而 registerOutParameter 方法將它的 JDBC 類型注冊為輸出參數(shù)。 setXXX 方法提供一個 Java 值,驅(qū)動程序先把這個值轉(zhuǎn)換為 JDBC 值,然后將它送到數(shù)據(jù)庫服務(wù)器。

          IN 值的 JDBC 類型和提供給 registerOutParameter 方法的 JDBC 類型應(yīng)該相同。如果要檢索輸出值,就要用對應(yīng)的 getXXX 方法。

          設(shè)有一個存儲過程 p2 的定義如下:

          CREATE OR REPLACE PROCEDURE p2(a1? INOUT? CHAR(20)) AS

          DECLARE CUR1 CURSOR FOR

          SELECT 廠商名

          FROM 廠商登記

          WHERE 廠商編號 = a1;

          BEGIN

          OPEN CUR1;

          FETCH CUR1 INTO a1;

          END;

          以下代碼中,方法 setString 把參數(shù)設(shè)為 “B0A05” 。然后, registerOutParameter 將該參數(shù)注冊為 JDBC VARCHAR 。執(zhí)行完該存儲過程后,將返回一個新的 JDBC VARCHAR 值。方法 getString 將把這個新值作為 Java String 類型返回。

          CallableStatement cstmt = con.prepareCall(call p2(?));

          cstmt.setString(1, B0A05);

          cstmt.registerOutParameter(1, java.sql.Types.VARCHAR);

          cstmt.executeUpdate();

          String x = cstmt.getString(1);

          ?

          5. 利用參數(shù)名進(jìn)行操作

          在通常的情況下一般采用參數(shù)索引來進(jìn)行賦值。 JDBC3.0 規(guī)范要求可以利用參數(shù)名來對參數(shù)進(jìn)行賦值, DM4 JDBC 3.0 驅(qū)動程序?qū)崿F(xiàn)了這一點(diǎn)。如果某個存儲過程的一些參數(shù)有默認(rèn)值,這時候采用參數(shù)名進(jìn)行賦值就非常有用,用戶可以只對那些沒有默認(rèn)值的參數(shù)進(jìn)行賦值。參數(shù)名可以通過調(diào)用 DatabaseMetaData.getProcedureColumns() 來獲得。

          下面的代碼中,存儲過程 p2 為上面那個存儲過程 p2 。利用參數(shù)名進(jìn)行操作:

          CallableStatement cstmt = con.prepareCall({CALL p2 (?)});

          cstmt.setString(a1, B0A05);

          cstmt.registerOutParameter(a1, java.sql.Types.VARCHAR);

          cstmt.executeUpdate();

          String x = cstmt.getString(a1);

          而且,在讀取參數(shù)的值和進(jìn)行參數(shù)注冊的時候, setXXX getXXX registerOutParameter 也都可以采用參數(shù)名來進(jìn)行操作。通過調(diào)用 DatabaseMetaData.supportsNamedParameters() 方法就可以確定 JDBC 驅(qū)動程序是否支持利用參數(shù)名來進(jìn)行操作。

          注意:在執(zhí)行同一條語句的過程中,不允許交叉使用參數(shù)索引和參數(shù)名來進(jìn)行操作,否則會拋出異常。

          ?

          6. 自定義方法列表

          為了實(shí)現(xiàn)對達(dá)夢數(shù)據(jù)庫所提供的時間間隔類型和帶納秒的時間類型的支持,在實(shí)現(xiàn) CallableStatement 接口的過程中,增加了一些自定義的擴(kuò)展方法。用戶將獲得的 CallableStatement 對象反溯成 DmdbCallableStatment 類型就可以訪問這些方法。這些方法所涉及到的擴(kuò)展類請參看 1.2.16 擴(kuò)展類這一節(jié)。

          1.2.3 自定義方法列表

          方法名 功能說明

          getINTERVALYM(int) 獲取指定列的 DmdbIntervalYM 類型值。

          getINTERVALYM(String) 獲取指定列的 DmdbIntervalYM 類型值。

          getINTERVALDT(int) 獲取指定列的 DmdbIntervalDT 類型值。

          getINTERVALDT(String) 獲取指定列的 DmdbIntervalDT 類型值。

          getTIME(int) 獲取指定列的 DmdbTime 類型值。

          getTIME(String) 獲取指定列的 DmdbTime 類型值。

          setTIME(String, DmdbTime) 根據(jù)參數(shù)名來設(shè)置 DmdbTime 類型值。

          setINTERVALDT(String, DmdbIntervalDT) 根據(jù)參數(shù)名來設(shè)置 DmdbIntervalDT 類型值。

          setINTERVALYM(String, DmdbIntervalYM) 根據(jù)參數(shù)名來設(shè)置 DmdbIntervalYM 類型值。

          ?

          ?

          ?

          ResultSet

          ?

          1. 概述

          ResultSet 提供執(zhí)行 SQL 語句后從數(shù)據(jù)庫返回結(jié)果中獲取數(shù)據(jù)的方法。執(zhí)行 SQL 語句后數(shù)據(jù)庫返回結(jié)果被 JDBC 處理成結(jié)果集對象,可以用 ResultSet 對象的 next 方法以行為單位進(jìn)行瀏覽,用 getXXX 方法取出當(dāng)前行的某一列的值。

          通過 Statement PreparedStatement CallableStatement 三種不同類型的語句進(jìn)行查詢都可以返回 ResultSet 類型的對象。

          ?

          2. 行和光標(biāo)

          ResultSet 維護(hù)指向其當(dāng)前數(shù)據(jù)行的邏輯光標(biāo)。每調(diào)用一次 next 方法,光標(biāo)向下移動一行。最初它位于第一行之前,因此第一次調(diào)用 next 將把光標(biāo)置于第一行上,使它成為當(dāng)前行。隨著每次調(diào)用 next 導(dǎo)致光標(biāo)向下移動一行,按照從上至下的次序獲取 ResultSet 行。

          ResultSet 對象或?qū)?yīng)的 Statement 對象關(guān)閉之前,光標(biāo)一直保持有效。

          ?

          3.

          方法 getXXX 提供了獲取當(dāng)前行中某列值的途徑。在每一行內(nèi),可按任何次序獲取列值。

          列名或列號可用于標(biāo)識要從中獲取數(shù)據(jù)的列。例如,如果 ResultSet 對象 rs 的第二列名為 “title” ,則下列兩種方法都可以獲取存儲在該列中的值:

          String s = rs.getString(title);

          String s = rs.getString(2);

          注意列是從左至右編號的,并且從 1 開始。

          ?

          關(guān)于 ResultSet 中列的信息,可通過調(diào)用方法 ResultSet.getMetaData 得到。返回的 ResultSetMetaData 對象將給出其 ResultSet 對象各列的名稱、類型和其他屬性。

          ?

          4. 采用流方式獲取列值

          為了獲取大數(shù)據(jù)量的列, JDBC 驅(qū)動程序提供了四個獲取流的方法:

          getBinaryStream 返回只提供數(shù)據(jù)庫原字節(jié)而不進(jìn)行任何轉(zhuǎn)換的流。

          getAsciiStream 返回提供單字節(jié) ASCII 字符的流。

          getUnicodeStream 返回提供雙字節(jié) Unicode 字符的流。

          getCharacterStream 返回提供雙字節(jié) Unicode 字符的 java.io.Reader 流。

          在這四個函數(shù)中, JDBC 規(guī)范不推薦使用 getCharacterStream 方法,其功能可以用 getUnicodeStream 代替。

          ?

          5. NULL 結(jié)果值

          要確定給定結(jié)果值是否是 JDBC NULL ,必須先讀取該列,然后使用 ResultSet 對象的 wasNull 方法檢查該次讀取是否返回 JDBC NULL

          當(dāng)使用 ResultSet 對象的 getXXX 方法讀取 JDBC NULL 時,將返回下列值之一:

          Java null 值:對于返回 Java 對象的 getXXX 方法(如 getString getBigDecimal getBytes getDate getTime getTimestamp getAsciiStream getUnicodeStream getBinaryStream getObject 等)。

          零值:對于 getByte getShort getInt getLong getFloat getDouble

          false 值:對于 getBoolean

          ?

          6. 結(jié)果集增強(qiáng)特性

          JDBC 驅(qū)動程序中提供了符合 JDBC 2.0 標(biāo)準(zhǔn)的結(jié)果集增強(qiáng)特性:可滾動、可更新結(jié)果集。及 JDBC3.0 標(biāo)準(zhǔn)的可持有性。

          (1) 結(jié)果集的可滾動性

          通過執(zhí)行語句而創(chuàng)建的結(jié)果集不僅支持向前(從第一行到最后一行)瀏覽內(nèi)容,而且還支持向后(從最后一行到第一行)瀏覽內(nèi)容的能力。支持這種能力的結(jié)果集被稱為可滾動的結(jié)果集。可滾動的結(jié)果集同時也支持相對定位和絕對定位。絕對定位指的是通過指定在結(jié)果集中的絕對位置而直接移動到某行的能力,而相對定位則指的是通過指定相對于當(dāng)前行的位置來移動到某行的能力。

          ?

          ?JDBC 驅(qū)動程序中支持只向前滾結(jié)果集 (ResultSet.TYPE_FORWARD_ONLY) 和滾動不敏感結(jié)果集 (ResultSet.TYPE_SCROLL_INSENSITIVE) 兩種結(jié)果集類型,不支持滾動敏感結(jié)果集 (ResultSet.TYPE_SCROLL_SENSITIVE) 。當(dāng)結(jié)果集為滾動不敏感結(jié)果集時,它提供所含基本數(shù)據(jù)的靜態(tài)視圖,即結(jié)果集中各行的成員順序、列值通常都是固定的。

          ?

          (2) 結(jié)果集的可更新性

          DM4 JDBC 驅(qū)動程序中提供了兩種結(jié)果集并發(fā)類型:只讀結(jié)果集 (ResultSet.CONCUR_READ_ONLY) 和可更新結(jié)果集 (ResultSet.CONCUR_UPDATABLE) 。采用只讀并發(fā)類型的結(jié)果集不允許對其內(nèi)容進(jìn)行更新。可更新的結(jié)果集支持結(jié)果集的更新操作。

          ?

          (3) 結(jié)果集的可持有性

          JDBC 3.0 提供了兩種結(jié)果集可持有類型:提交關(guān)閉結(jié)果集 (ResultSet.CLOSE_CURSORS_AT_COMMIT) 和跨結(jié)果集提交 (ResultSet.HOLD_CURSORS_OVER_COMMIT) 。采用提交關(guān)閉結(jié)果集類型的結(jié)果集在事務(wù)提交之后被關(guān)閉,而跨結(jié)果集提交類型的結(jié)果集在事務(wù)提交之后仍能保持打開狀態(tài)。

          通過 DatabaseMetaData.supportsHoldability() 方法可以確定驅(qū)動程序是否支持結(jié)果集的可持有性。目前 DM4 支持這兩種類型。

          ?

          (4) 性能優(yōu)化

          JDBC 驅(qū)動程序的結(jié)果集對象中提供了方法 setFetchDirection setFetchSize 來設(shè)置缺省檢索結(jié)果集的方向和缺省一次從數(shù)據(jù)庫獲取的記錄條數(shù)。它們的含義與用法和語句對象中的同名函數(shù)是相同的。

          ?

          7. 更新大對象數(shù)據(jù)

          JDBC 2.0 驅(qū)動程序就支持可更新的結(jié)果集,但是對 LOB 對象只能讀取,而不能更新,這也是 JDBC 2.0 標(biāo)準(zhǔn)所規(guī)定的。而 JDBC 3.0 規(guī)范規(guī)定用戶可以對 LOB 對象進(jìn)行更新, DM4 JDBC 3.0 驅(qū)動程序中實(shí)現(xiàn)了這一點(diǎn):

          Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,

          ResultSet.CONCUR_UPDATABLE);

          ResultSet rs = stmt.executeQuery(select comment from booklist +

          where isbn = 140185852);

          rs.next();

          Clob commentClob = new Clob(...)

          rs.updateClob(author, commentClob);? // commentClob is a Clob Object

          rs.updateRow();

          ?

          ?

          ?

          ?ResultSetMetaData

          ?

          1. 概述

          ResultSetMetaData 提供許多方法,用于讀取 ResultSet 對象返回數(shù)據(jù)的元信息。包括:列名、列數(shù)據(jù)類型、列所屬的表、以及列是否允許為 NULL 值等,通過這些方法可以確定結(jié)果集中列的一些信息。

          2. 創(chuàng)建結(jié)果集元數(shù)據(jù)對象

          結(jié)果集元數(shù)據(jù)是用來描述結(jié)果集的特征,所以,需要首先執(zhí)行查詢獲得結(jié)果集,才能創(chuàng)建結(jié)果集元數(shù)據(jù)對象。

          3. 創(chuàng)建 ResultSetMetaData 對象如下例所示:

          假如有一個表 TESTTABLE(no int,name varchar(10)) ,利用下面的代碼就可以知道這個表的各個列的類型:

          ResultSet rs = stmt.executeQuery(SELECT * FROM TESTTABLE);

          ResultSetMetaData rsmd = rs.getMetaData();

          for(int i = 1; i <= rsmd.getColumnCount(); i ++)

          {

          ?? String typeName = rsmd.getColumnTypeName(i);

          ?? System.out.println( + i + 列的類型為: + typeName);

          }

          ?

          DatabaseMetaData

          1. 概述

          DatabaseMetaData 提供了許多方法,用于獲取數(shù)據(jù)庫的元數(shù)據(jù)信息。包括:描述數(shù)據(jù)庫特征的信息 ( 如是否支持多個結(jié)果集 ) 、目錄信息、模式信息、表信息、表權(quán)限信息、表列信息、存儲過程信息等。 DatabaseMetaData 有部分方法以 ResultSet 對象的形式返回結(jié)果,可以用 ResultSet 對象的 getXXX() 方法獲取所需的數(shù)據(jù)。

          ?

          2. 創(chuàng)建數(shù)據(jù)庫元數(shù)據(jù)對象

          數(shù)據(jù)庫元數(shù)據(jù)對象由連接對象創(chuàng)建。以下代碼創(chuàng)建 DatabaseMetaData 對象(其中 con 為連接對象):

          DatabaseMetaData dbmd = con.getMetaData();

          利用該數(shù)據(jù)庫元數(shù)據(jù)對象就可以獲得一些有關(guān)數(shù)據(jù)庫和 JDBC 驅(qū)動程序的信息:

          String databaseName = dbmd.getDatabaseProductName();? // 數(shù)據(jù)庫產(chǎn)品的名稱

          int majorVersion = dbmd.getJDBCMajorVersion();? // JDBC 驅(qū)動程序的主版本號

          String []types ={TABLE};

          ResultSet tablesInfor = dbmd.getTables(null,? null,? “*TE%”,? types);

          ?

          數(shù)據(jù)類型訪問

          1 .概述

          對數(shù)據(jù)的訪問主要是

          (1) 通過 PreparedStatement 對象、 CallableStatement 對象的 setXXX 方法以及 ResultSet 對象的 updateXXX() 方法進(jìn)行設(shè)置 ;

          ?(2) 通過 CallableStatement 對象、 ResultSet 對象的 getXXX() 方法來進(jìn)行檢索。

          ?

          2 .各個類型能采用的 setXXX 方法或 updateXXX 方法

          請參看 SUN 公司的 JDBC 3.0 specification 文檔第 186 頁的 TABLE-6 。一般地,只要把里面的 getXXX 改為 setXXX updateXXX 即可。

          ?

          3 .各個類型能采用的 getXXX 方法

          請參看 SUN 公司的 JDBC 3.0 specification 文檔第 186 頁的 TABLE-6

          ?

          ?

          ?ParameterMetaData

          ?

          1 .概述

          參數(shù)元數(shù)據(jù)是 JDBC 3.0 標(biāo)準(zhǔn)新引入的接口,它主要是對 PreparedStatement CallableStatement 對象中的 ? 參數(shù)進(jìn)行描述,例如參數(shù)的個數(shù)、參數(shù)的類型、參數(shù)的精度等信息,類似于 ResultSetMetaData 接口。通過引入這個接口,就可以對參數(shù)進(jìn)行較為詳細(xì)、準(zhǔn)確的操作。

          2 .創(chuàng)建參數(shù)元數(shù)據(jù)對象

          通過調(diào)用 PreparedStatement CallableStatement 對象的 getParameterMetaData() 方法就可以獲得該預(yù)編譯對象的 ParameterMetaData 對象:

          ParameterMetaData pmd = pstmt.getParameterMetaData();

          然后就可以利用這個對象來獲得一些有關(guān)參數(shù)描述的信息:

          // 獲取參數(shù)個數(shù)

          int paraCount = pmd.getParameterCount();

          for(int i = 1; i <= paraCount; i ++) {

          // 獲取參數(shù)類型

          System.out.println(The Type of Parameter(+i+) is + ptmt.getParameterType(i));

          // 獲取參數(shù)類型名

          System.out.println(The Type Name of Parameter(+i+) is

          + ptmt.getParameterTypeName(i));

          // 獲取參數(shù)精度

          System.out.println(The Precision of Parameter(+i+) is + ptmt.getPrecision(i));

          // 獲取參數(shù)是否為空

          System.out.println(Parameter(+i+) is nullable? + ptmt.isNullable (i));

          }

          ?

          ?

          ? 大對象

          ?

          1 .概述

          JDBC 標(biāo)準(zhǔn)為了增強(qiáng)對大數(shù)據(jù)對象的操作,在 JDBC 3.0 標(biāo)準(zhǔn)中增加了 java.sql.Blob java.sql.Clob 這兩個接口。這兩個接口定義了許多操作大對象的方法,通過這些方法就可以對大對象的內(nèi)容進(jìn)行操作。

          ?

          2 .產(chǎn)生 Lob 對象

          ResultSet CallableStatement 對象中調(diào)用 getBlob() getClob() 方法就可以獲得 Blob 對象和 Clob 對象:

          Blob blob = rs.getBlob(1);

          Clob clob = rs.getClob(2);

          ?

          3 .設(shè)置 Lob 對象

          Lob 對象可以像普通數(shù)據(jù)類型一樣作為參數(shù)來進(jìn)行參數(shù)賦值,在操作 PreparedStatement CallableStatement ResultSet 對象時使用:

          PreparedStatement pstmt = conn.prepareStatement(INSERT INTO bio (image, text) “ +

          “VALUES (?, ?));

          //authorImage is a Blob Object

          pstmt.setBlob(1, authorImage);

          //authorBio is a Clob Object

          pstmt.setClob(2, authorBio);

          在一個可更新的結(jié)果集中,也可以利用 updateBlob(int,Blob) updateClob(int,Clob) 來更新當(dāng)前行。

          ?

          4 .改變 Lob 對象的內(nèi)容

          Lob 接口提供了方法讓用戶可以對 Lob 對象的內(nèi)容進(jìn)行任意修改: ?

          byte[] val = {0,1,2,3,4};

          ?

          Blob data = rs.getBlob(DATA);

          int numWritten = data.setBytes(1, val); // 在指定的位置插入數(shù)據(jù)

          PreparedStatement ps = conn.prepareStatement(UPDATE datatab SET data = ?);

          ps.setBlob(DATA, data);

          ps.executeUpdate();

          ?

          ?

          ?

          ?Savepoint

          ?

          1 .概述

          為了增加對事務(wù)的控制, JDBC 規(guī)范 3.0 增加了 Savepoint 這個接口。它代表一個邏輯事務(wù)點(diǎn)。在非自動提交模式下,一個事務(wù)中可以設(shè)置多個 Savepoint 。這樣在回滾時,可以回滾到指定的 Savepoint ,從事務(wù)開始到該 Savepoint 之間的操作依然保留著。這就提高了事務(wù)處理的粒度,更好地操縱數(shù)據(jù)。

          Savepoint 分為命名的和未命名的兩種。未命名的用系統(tǒng)分配的 ID 作為標(biāo)識。同時可以通過 DatabaseMetaData.supportsSavepoint() 來判斷 JDBC 驅(qū)動程序是否支持 Savepoint

          ?

          2 .操作 Savepoint

          Savepoint 的操作位于 Conncetion 接口:

          Statement stmt = conn.createStatement();

          int rows = stmt.executeUpdate(insert into tab1(col) values(' first') ); // 插入第一條數(shù)據(jù)

          Savepoint svpt1 = conn.setSavepoint(SAVEPOINT_1); // 設(shè)置一個 Savepoint

          rows = stmt.executeUpdate(intert into tab1(col) values('second') ); // 插入第二條數(shù)據(jù)

          ……

          conn.rollback(svpt1); // 回滾到指定的 Savepoint

          ……

          conn.commit(); // 提交事務(wù) , 真正在數(shù)據(jù)庫中僅插入了第一條數(shù)據(jù)

          這樣,數(shù)據(jù)庫中僅增加了第一次插入的那條記錄。注意:在使用 Savepoint 之前,一定要把當(dāng)前連接設(shè)置為非自動提交模式。

          在事務(wù)提交之后,先前事務(wù)中的所有 Savepoint 都自動取消。如果有兩個 Savepoint ,當(dāng)事務(wù)回滾到前面的那個 Savepoint 時,后面的這個 Savepoint 也自動取消。

          ?

          autoGenerated Key

          ?

          在很多數(shù)據(jù)庫中,插入一條新的記錄時數(shù)據(jù)庫會為新增的記錄自動產(chǎn)生一個唯一的標(biāo)識。 JDBC3.0 規(guī)范中的 Statement 新增了一個方法: getGeneratedKeys ,利用這個方法就可以檢索出系統(tǒng)自動為插入的新行所產(chǎn)生的關(guān)鍵字。可以傳遞一個 Statement.RETURN_GENERATED_KEYS 標(biāo)識給 Statement 對象的 execute executeUpdate() 的方法或者 PreparedStatement 對象的一些方法,這樣在執(zhí)行完這些方法之后就可以檢索新產(chǎn)生的關(guān)鍵字。

          Statement stmt? = conn.createStatement();

          int rows = stmt.executeUpdate(insert into orders(isbn,customerid) values(1953, 'billg') ,

          Statement.RETURN_GENERATED_KEYS);

          ResultSet rs = stmt.getGeneratedKeys();

          boolean b = rs.next();

          if (b)

          {

          // 檢索新產(chǎn)生的關(guān)鍵字的值

          ……

          }

          為了檢索方便,用戶也可以為自動產(chǎn)生的關(guān)鍵字指定列名或者索引:

          String[] keyColumn = {order_id};

          … …

          Statement stmt = conn.createStatement();

          int rows = stmt.executeUpdate(insert into orders (isbn,customerid) values(9664, 'Billg') ,keyColumn);

          ResultSet rs = stmt.getGeneratedKeys();

          while(rs.next())

          {

          // 檢索新產(chǎn)生的關(guān)鍵字的值

          byte[] bs = rs.getBytes(order_id);

          }

          ……

          JDBC 驅(qū)動程序是否支持自動產(chǎn)生的關(guān)鍵字,可以通過 DataBaseMetaData.supportsGetGeneratedKeys 來判斷。

          ?

          ?

          ? 數(shù)據(jù)源 DataSource

          ?

          數(shù)據(jù)源是 JDBC 2.0 規(guī)范作為擴(kuò)展包引入的,在 JDBC 3.0 規(guī)范中成為核心 API 。數(shù)據(jù)源不僅能夠從功能上完全取代利用 DriverManager 建立連接的方式,而且具有以下幾點(diǎn)優(yōu)勢:

          (1) 增強(qiáng)了代碼的可移植性;

          (2) 方便了代碼的維護(hù);

          (3) 利用連接池來提高系統(tǒng)的性能。

          ?

          JDBC 驅(qū)動程序提供了對數(shù)據(jù)源的支持,實(shí)現(xiàn)了 javax.sql.DataSource 接口和 java.sql.ConnectionPoolDataSource 接口。用戶通過 javax.sql.DataSource 接口來建立連接。

          ?

          使用數(shù)據(jù)源來建立連接時,

          首先要向 JNDI 注冊一個數(shù)據(jù)源。在建立連接的時候,首先通過 JNDI 來獲得要使用的數(shù)據(jù)源:

          DataSource ds = (DataSource) ctx.lookup(datasourceName)

          然后使用這個數(shù)據(jù)源來建立連接對象:

          Connection con = ds.getConnection()

          該連接同通過 DriverManager 所建立的連接是一樣的。

          ?

          實(shí)現(xiàn) javax.sql.ConnectionPoolDataSource 接口是為了提高系統(tǒng)的性能。通過設(shè)置一個連接緩沖區(qū),在其中保持?jǐn)?shù)目較小的物理連接的方式,這個連接緩沖區(qū)由大量的并行用戶共享和重新使用,從而避免在每次需要時建立一個新的物理連接,以及當(dāng)其被釋放時關(guān)閉該連接的昂貴操作。該連接池是 JDBC 提供系統(tǒng)性能的一種措施,是在 JDBC 內(nèi)部實(shí)現(xiàn)的,能夠?yàn)橛脩籼峁┩该鞯母咚倬彌_連接訪問。用戶利用數(shù)據(jù)源來建立連接的應(yīng)用不需為此做出任何代碼上的變動。

          posted on 2006-07-25 08:49 Lizzie 閱讀(2614) 評論(0)  編輯  收藏 所屬分類: 專業(yè)積木

          <2006年7月>
          2526272829301
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 东阿县| 太保市| 临海市| 渭源县| 庆安县| 崇信县| 龙川县| 子长县| 芮城县| 望城县| 遂溪县| 天峨县| 榕江县| 玉屏| 霍林郭勒市| 东兰县| 桂东县| 井研县| 崇左市| 长海县| 诸城市| 尉氏县| 鸡东县| 锡林浩特市| 翁牛特旗| 太湖县| 佛教| 荥经县| 滕州市| 淮北市| 博湖县| 汉寿县| 河曲县| 德化县| 峨边| 循化| 安国市| 綦江县| 报价| 离岛区| 洪湖市|