JDBC
提供三種類型的語句對象:
Statement
,
PreparedStatement
,
CallableStatement
。
其中
PreparedStatement
是
Statement
的子類,
CallableStatement
是
PreparedStatement
的子類。每一種語句對象用來運行特定類型的
SQL
語句。
Statement
對象用來運行簡單類型的
SQL
語句,語句中無需指定參數。
PreparedStatement
對象用來運行包含(或不包含)
IN
類型參數的預編譯
SQL
語句。
CallableStatement
對象用來調用數據庫存儲過程。
?
?
Statement
1.
概述
Statement
對象用于將
SQL
語句發送到數據庫服務器。
?
2.
創建
Statement
對象
建立連接后,
Statement
對象用
Connection
對象的
createStatement
方法創建,以下代碼創建
Statement
對象:
Connection con = DriverManager.getConnection(url, SYSDBA, SYSDBA);
Statement stmt = con.createStatement();
?
3.
使用
Statement
對象執行語句
Statement
接口提供了三種執行
SQL
語句的方法:
executeQuery
、
executeUpdate
和
execute
。
?
方法
executeQuery
用于產生單個結果集的語句,例如
SELECT
語句。
?
方法
executeUpdate
用于執行
INSERT
、
UPDATE
或
DELETE
語句以及
SQL DDL
語句,如
CREATE TABLE
和
DROP TABLE
。
INSERT
、
UPDATE
或
DELETE
語句的效果是修改表中零行或多行中的一列或多列。
executeUpdate
的返回值是一個整數,表示受影響的行數。對于
CREATE TABLE
或
DROP TABLE
等
DDL
語句,
executeUpdate
的返回值總為零。
?
方法
execute
用于執行返回多個結果集、多個更新元組數或二者組合的語句。
?
執行語句的三種方法都將關閉所調用的
Statement
對象的當前打開結果集(如果存在)。這意味著在重新執行
Statement
對象之前,需要完成對當前
ResultSet
對象的處理。
?
4.
關閉
Statement
對象
Statement
對象可由
Java
垃圾收集程序自動關閉。但作為一種好的編程風格,應在不需要
Statement
對象時顯式地關閉它們。這將立即釋放數據庫服務器資源,有助于避免潛在的內存問題。
?
?
?
PreparedStatement
1.
概述
PreparedStatement
繼承
Statement
,并與之在兩方面有所不同:
PreparedStatement
對象包含已編譯的
SQL
語句,語句已經
“
準備好
”
。
包含于
PreparedStatement
對象中的
SQL
語句可具有一個或多個
IN
參數。
IN
參數的值在
SQL
語句創建時未被指定。相反,該語句為每個
IN
參數保留一個問號(
“
?
”
)作為占位符。每個問號所對應的值必須在該語句執行之前,通過適當的
setXXX
方法來提供。
由于
PreparedStatement
對象已預編譯過,所以其執行速度要快于
Statement
對象。因此,需要多次重復執行的
SQL
語句經常創建為
PreparedStatement
對象,以提高效率。
?
作為
Statement
的子類,
PreparedStatement
繼承了
Statement
的所有功能。另外它還添加了一整套方法,用于設置發送給數據庫以取代
IN
參數占位符的值。同時,三種方法
execute
、
executeQuery
和
executeUpdate
能執行設置好參數的語句對象。
?
2.
創建
PreparedStatement
對象
以下的代碼段(其中
con
是
Connection
對象)創建一個
PreparedStatement
對象:
PreparedStatement pstmt = con.prepareStatement( UPDATE
廠商登記
SET
廠商名
= ? WHERE
廠商編號
= ?);
對象
pstmt
包含語句
UPDATE
廠商登記
SET
廠商名
= ? WHERE
廠商編號
= ?
,該語句帶兩個
IN
參數占位符,它已發送給數據庫,并由服務器為其執行作好了準備。
?
3.
傳遞
IN
參數
在執行
PreparedStatement
對象之前,必須設置每個
?
參數的值。這可通過調用
setXXX
方法來完成,其中
XXX
是與該參數相應的類型。例如,如果參數具有
Java
類型
String
,則使用的方法就是
setString
。對于不同類型的參數,一般都會有一個推薦的設置方法和多個可行的設置方法。
setXXX
方法的第一個參數是要設置的參數的序號(從
1
算起),第二個參數是設置給該參數的值。譬如,以下代碼將第一個參數設為
“
中華電視機廠
”
,第二個參數設為
“B0A01”
:
pstmt.setString(1,
中華電視機廠
);
pstmt.setString(2, B0A01);
每當設置了給定語句的參數值,就可執行該語句。設置一組新的參數值之前,應先調用
clearParameters
方法清除原先設置的參數值。
?
4.
使用
setObject
方法
:
可顯式地將輸入參數轉換為特定的
JDBC
類型。
該方法可以接受三個參數,其中第三個參數用來指定目標
JDBC
類型。將
Java Object
發送給數據庫之前,驅動程序將把它轉換為指定的
JDBC
類型。
如果沒有指定
JDBC
類型,驅動程序就會將
Java Object
映射到其缺省的
JDBC
類型,然后將它發送到數據庫。這與常規的
setXXX
方法類似。在這兩種情況下,驅動程序在將值發送到數據庫之前,會將該值的
Java
類型映射為適當的
JDBC
類型。
二者的差別在于
setXXX
方法使用從
Java
類型到
JDBC
類型的標準映射,而
setObject
方法使用從
Java Object
類型到
JDBC
類型的映射。
?
方法
setObject
允許接受所有
Java
對象,這使應用程序更為通用,并可在運行時接受參數的輸入。這樣,如果用戶在編輯應用程序時不能確定輸入類型,可以通過使用
setObject
,對應用程序賦予可接受的
Java
對象,然后由
JDBC
驅動程序自動將其轉換成數據庫所需的
JDBC
類型。但如果用戶已經清楚輸入類型,使用相應的
setXXX
方法是值得推薦的,可以提高效率。
?
5.
將
JDBC NULL
作為
IN
參數發送
setNull
方法允許程序員將
JDBC NULL
值作為
IN
參數發送給數據庫。在這種情況下,可以把參數的目標
JDBC
類型指定為任意值,同時參數的目標精度也不再起作用。
?
6.
發送大的
IN
參數
setBytes
和
setString
方法能夠發送無限量的數據。但是,內存要足夠容納相關數據。有時程序員更喜歡用較小的塊傳遞大型的數據,這可通過將
IN
參數設置為
Java
輸入流來完成。當語句執行時,
JDBC
驅動程序將重復調用該輸入流,讀取其內容并將它們當作實際參數數據傳輸。
JDBC
提供了四種將
IN
參數設置為輸入流的方法:
setBinaryStream
用于字節流,
setAsciiStream
用于
ASCII
字符流,
setUnicodeStream
用于
Unicode
字符流,從
JDK1.2
起,輸入字符流的新方法為
setCharacterStream
,而
setAsciiStream
和
setUnicodeStream
已經很少用。
?
7.
獲得參數元數據
JDBC 3.0
實現了
getParameterMetaData()
方法,通過這個方法可以獲得有關
IN
參數的各種屬性信息,比如類型、精度、刻度等信息,類似于結果集元數據的內容。通過這些信息,用戶可以更準確地設置
IN
參數的值。
`
在下面的代碼中涉及到了這種方法:
PreparedStatement pstmt = conn.prepareStatement(SELECT * FROM BOOKLIST “ + “WHERE ISBN = ? );
...
//
獲得參數元數據對象
ParameterMetaData pmd = pstmt.getParameterMetaData();
//
獲得參數的個數
int paramCount = pstmt.getParameterCount();
//
獲得第一參數的類型
int colType = pmd.getParameterType(1);
…
8.
自定義方法列表
為了實現對達夢數據庫所提供的時間間隔類型和帶納秒的時間類型的支持,在實現
PreparedStatement
接口的過程中,增加了一些自定義的擴展方法。用戶將獲得的
PreparedStatement
對象反溯成
DmdbPreparedStatment
類型就可以訪問這些方法。
?
?
?
CallableStatement
1.
概述
CallableStatement
用來運行
SQL
存儲過程。存儲過程是數據庫中已經存在的
SQL
語句,它通過名字調用。
CallableStatement
是
PreparedStatement
的子類。
CallableStatement
中定義的方法用于處理
OUT
參數或
INOUT
參數的輸出部分:注冊
OUT
參數的
JDBC
類型(一般
SQL
類型)、從這些參數中檢索結果,或者檢查所返回的值是否為
JDBC NULL
。
?
2.
創建
CallableStatement
對象
CallableStatement
對象是用
Connection.prepareCall
創建的。
以下代碼創建
CallableStatement
對象,其中含有對存儲過程
p1
的調用,
con
為連接對象:
CallableStatement cstmt = con.prepareCall(call p1(?, ?));
其中
?
占位符為
IN
、
OUT
還是
INOUT
參數,取決于存儲過程
p1
。
?
3. IN
和
OUT
參數
將
IN
參數傳給
CallableStatement
對象是通過
setXXX
方法完成的。該方法繼承自
PreparedStatement
。所傳入參數的類型決定了所用的
setXXX
方法(例如,用
setString
來傳入
String
值等)。
如果存儲過程返回
OUT
參數,則在執行
CallableStatement
對象之前必須先注冊每個
OUT
參數的
JDBC
類型,有的參數還要同時提供刻度。注冊
JDBC
類型是用
registerOutParameter
方法來完成的。語句執行完后,
CallableStatement
的
getXXX
方法將取回參數值。其中
XXX
是為各參數所注冊的
JDBC
類型所對應的
Java
類型。換言之,
registerOutParameter
使用的是
JDBC
類型(因此它與數據庫返回的
JDBC
類型匹配),而
getXXX
將之轉換為
Java
類型。
設存儲過程
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
參數,執行由
cstmt
所調用的存儲過程,然后檢索通過
OUT
參數返回的值。方法
getString
從
OUT
參數中取出字符串:
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
參數
如果參數為既接受輸入又接受輸出的參數類型(
INOUT
參數),那么除了調用
registerOutParameter
方法外,還要調用對應的
setXXX
方法(繼承自
PreparedStatement
)。
setXXX
方法將參數值設置為輸入參數,而
registerOutParameter
方法將它的
JDBC
類型注冊為輸出參數。
setXXX
方法提供一個
Java
值,驅動程序先把這個值轉換為
JDBC
值,然后將它送到數據庫服務器。
該
IN
值的
JDBC
類型和提供給
registerOutParameter
方法的
JDBC
類型應該相同。如果要檢索輸出值,就要用對應的
getXXX
方法。
設有一個存儲過程
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
把參數設為
“B0A05”
。然后,
registerOutParameter
將該參數注冊為
JDBC VARCHAR
。執行完該存儲過程后,將返回一個新的
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.
利用參數名進行操作
在通常的情況下一般采用參數索引來進行賦值。
JDBC3.0
規范要求可以利用參數名來對參數進行賦值,
DM4 JDBC 3.0
驅動程序實現了這一點。如果某個存儲過程的一些參數有默認值,這時候采用參數名進行賦值就非常有用,用戶可以只對那些沒有默認值的參數進行賦值。參數名可以通過調用
DatabaseMetaData.getProcedureColumns()
來獲得。
下面的代碼中,存儲過程
p2
為上面那個存儲過程
p2
。利用參數名進行操作:
CallableStatement cstmt = con.prepareCall({CALL p2 (?)});
cstmt.setString(a1, B0A05);
cstmt.registerOutParameter(a1, java.sql.Types.VARCHAR);
cstmt.executeUpdate();
String x = cstmt.getString(a1);
而且,在讀取參數的值和進行參數注冊的時候,
setXXX
、
getXXX
、
registerOutParameter
也都可以采用參數名來進行操作。通過調用
DatabaseMetaData.supportsNamedParameters()
方法就可以確定
JDBC
驅動程序是否支持利用參數名來進行操作。
注意:在執行同一條語句的過程中,不允許交叉使用參數索引和參數名來進行操作,否則會拋出異常。
?
6.
自定義方法列表
為了實現對達夢數據庫所提供的時間間隔類型和帶納秒的時間類型的支持,在實現
CallableStatement
接口的過程中,增加了一些自定義的擴展方法。用戶將獲得的
CallableStatement
對象反溯成
DmdbCallableStatment
類型就可以訪問這些方法。這些方法所涉及到的擴展類請參看
1.2.16
擴展類這一節。
表
1.2.3
:
自定義方法列表
方法名
功能說明
getINTERVALYM(int)
獲取指定列的
DmdbIntervalYM
類型值。
getINTERVALYM(String)
獲取指定列的
DmdbIntervalYM
類型值。
getINTERVALDT(int)
獲取指定列的
DmdbIntervalDT
類型值。
getINTERVALDT(String)
獲取指定列的
DmdbIntervalDT
類型值。
getTIME(int)
獲取指定列的
DmdbTime
類型值。
getTIME(String)
獲取指定列的
DmdbTime
類型值。
setTIME(String, DmdbTime)
根據參數名來設置
DmdbTime
類型值。
setINTERVALDT(String, DmdbIntervalDT)
根據參數名來設置
DmdbIntervalDT
類型值。
setINTERVALYM(String, DmdbIntervalYM)
根據參數名來設置
DmdbIntervalYM
類型值。
?
?
?
ResultSet
?
1.
概述
ResultSet
提供執行
SQL
語句后從數據庫返回結果中獲取數據的方法。執行
SQL
語句后數據庫返回結果被
JDBC
處理成結果集對象,可以用
ResultSet
對象的
next
方法以行為單位進行瀏覽,用
getXXX
方法取出當前行的某一列的值。
通過
Statement
,
PreparedStatement
,
CallableStatement
三種不同類型的語句進行查詢都可以返回
ResultSet
類型的對象。
?
2.
行和光標
ResultSet
維護指向其當前數據行的邏輯光標。每調用一次
next
方法,光標向下移動一行。最初它位于第一行之前,因此第一次調用
next
將把光標置于第一行上,使它成為當前行。隨著每次調用
next
導致光標向下移動一行,按照從上至下的次序獲取
ResultSet
行。
在
ResultSet
對象或對應的
Statement
對象關閉之前,光標一直保持有效。
?
3.
列
方法
getXXX
提供了獲取當前行中某列值的途徑。在每一行內,可按任何次序獲取列值。
列名或列號可用于標識要從中獲取數據的列。例如,如果
ResultSet
對象
rs
的第二列名為
“title”
,則下列兩種方法都可以獲取存儲在該列中的值:
String s = rs.getString(title);
String s = rs.getString(2);
注意列是從左至右編號的,并且從
1
開始。
?
關于
ResultSet
中列的信息,可通過調用方法
ResultSet.getMetaData
得到。返回的
ResultSetMetaData
對象將給出其
ResultSet
對象各列的名稱、類型和其他屬性。
?
4.
采用流方式獲取列值
為了獲取大數據量的列,
JDBC
驅動程序提供了四個獲取流的方法:
getBinaryStream
返回只提供數據庫原字節而不進行任何轉換的流。
getAsciiStream
返回提供單字節
ASCII
字符的流。
getUnicodeStream
返回提供雙字節
Unicode
字符的流。
getCharacterStream
返回提供雙字節
Unicode
字符的
java.io.Reader
流。
在這四個函數中,
JDBC
規范不推薦使用
getCharacterStream
方法,其功能可以用
getUnicodeStream
代替。
?
5. NULL
結果值
要確定給定結果值是否是
JDBC NULL
,必須先讀取該列,然后使用
ResultSet
對象的
wasNull
方法檢查該次讀取是否返回
JDBC NULL
。
當使用
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.
結果集增強特性
在
JDBC
驅動程序中提供了符合
JDBC 2.0
標準的結果集增強特性:可滾動、可更新結果集。及
JDBC3.0
標準的可持有性。
(1)
結果集的可滾動性
通過執行語句而創建的結果集不僅支持向前(從第一行到最后一行)瀏覽內容,而且還支持向后(從最后一行到第一行)瀏覽內容的能力。支持這種能力的結果集被稱為可滾動的結果集。可滾動的結果集同時也支持相對定位和絕對定位。絕對定位指的是通過指定在結果集中的絕對位置而直接移動到某行的能力,而相對定位則指的是通過指定相對于當前行的位置來移動到某行的能力。
?
?JDBC
驅動程序中支持只向前滾結果集
(ResultSet.TYPE_FORWARD_ONLY)
和滾動不敏感結果集
(ResultSet.TYPE_SCROLL_INSENSITIVE)
兩種結果集類型,不支持滾動敏感結果集
(ResultSet.TYPE_SCROLL_SENSITIVE)
。當結果集為滾動不敏感結果集時,它提供所含基本數據的靜態視圖,即結果集中各行的成員順序、列值通常都是固定的。
?
(2)
結果集的可更新性
DM4 JDBC
驅動程序中提供了兩種結果集并發類型:只讀結果集
(ResultSet.CONCUR_READ_ONLY)
和可更新結果集
(ResultSet.CONCUR_UPDATABLE)
。采用只讀并發類型的結果集不允許對其內容進行更新。可更新的結果集支持結果集的更新操作。
?
(3)
結果集的可持有性
JDBC 3.0
提供了兩種結果集可持有類型:提交關閉結果集
(ResultSet.CLOSE_CURSORS_AT_COMMIT)
和跨結果集提交
(ResultSet.HOLD_CURSORS_OVER_COMMIT)
。采用提交關閉結果集類型的結果集在事務提交之后被關閉,而跨結果集提交類型的結果集在事務提交之后仍能保持打開狀態。
通過
DatabaseMetaData.supportsHoldability()
方法可以確定驅動程序是否支持結果集的可持有性。目前
DM4
支持這兩種類型。
?
(4)
性能優化
JDBC
驅動程序的結果集對象中提供了方法
setFetchDirection
和
setFetchSize
來設置缺省檢索結果集的方向和缺省一次從數據庫獲取的記錄條數。它們的含義與用法和語句對象中的同名函數是相同的。
?
7.
更新大對象數據
從
JDBC 2.0
驅動程序就支持可更新的結果集,但是對
LOB
對象只能讀取,而不能更新,這也是
JDBC 2.0
標準所規定的。而
JDBC 3.0
規范規定用戶可以對
LOB
對象進行更新,
DM4 JDBC 3.0
驅動程序中實現了這一點:
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
對象返回數據的元信息。包括:列名、列數據類型、列所屬的表、以及列是否允許為
NULL
值等,通過這些方法可以確定結果集中列的一些信息。
2.
創建結果集元數據對象
結果集元數據是用來描述結果集的特征,所以,需要首先執行查詢獲得結果集,才能創建結果集元數據對象。
3.
創建
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
提供了許多方法,用于獲取數據庫的元數據信息。包括:描述數據庫特征的信息
(
如是否支持多個結果集
)
、目錄信息、模式信息、表信息、表權限信息、表列信息、存儲過程信息等。
DatabaseMetaData
有部分方法以
ResultSet
對象的形式返回結果,可以用
ResultSet
對象的
getXXX()
方法獲取所需的數據。
?
2.
創建數據庫元數據對象
數據庫元數據對象由連接對象創建。以下代碼創建
DatabaseMetaData
對象(其中
con
為連接對象):
DatabaseMetaData dbmd = con.getMetaData();
利用該數據庫元數據對象就可以獲得一些有關數據庫和
JDBC
驅動程序的信息:
String databaseName = dbmd.getDatabaseProductName();? //
數據庫產品的名稱
int majorVersion = dbmd.getJDBCMajorVersion();? // JDBC
驅動程序的主版本號
String []types ={TABLE};
ResultSet tablesInfor = dbmd.getTables(null,? null,? “*TE%”,? types);
?
數據類型訪問
1
.概述
對數據的訪問主要是
(1)
通過
PreparedStatement
對象、
CallableStatement
對象的
setXXX
方法以及
ResultSet
對象的
updateXXX()
方法進行設置
;
?(2)
通過
CallableStatement
對象、
ResultSet
對象的
getXXX()
方法來進行檢索。
?
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
.概述
參數元數據是
JDBC 3.0
標準新引入的接口,它主要是對
PreparedStatement
、
CallableStatement
對象中的
?
參數進行描述,例如參數的個數、參數的類型、參數的精度等信息,類似于
ResultSetMetaData
接口。通過引入這個接口,就可以對參數進行較為詳細、準確的操作。
2
.創建參數元數據對象
通過調用
PreparedStatement
或
CallableStatement
對象的
getParameterMetaData()
方法就可以獲得該預編譯對象的
ParameterMetaData
對象:
ParameterMetaData pmd = pstmt.getParameterMetaData();
然后就可以利用這個對象來獲得一些有關參數描述的信息:
//
獲取參數個數
int paraCount = pmd.getParameterCount();
for(int i = 1; i <= paraCount; i ++) {
//
獲取參數類型
System.out.println(The Type of Parameter(+i+) is + ptmt.getParameterType(i));
//
獲取參數類型名
System.out.println(The Type Name of Parameter(+i+) is
+ ptmt.getParameterTypeName(i));
//
獲取參數精度
System.out.println(The Precision of Parameter(+i+) is + ptmt.getPrecision(i));
//
獲取參數是否為空
System.out.println(Parameter(+i+) is nullable? + ptmt.isNullable (i));
}
?
?
?
大對象
?
1
.概述
JDBC
標準為了增強對大數據對象的操作,在
JDBC 3.0
標準中增加了
java.sql.Blob
和
java.sql.Clob
這兩個接口。這兩個接口定義了許多操作大對象的方法,通過這些方法就可以對大對象的內容進行操作。
?
2
.產生
Lob
對象
在
ResultSet
和
CallableStatement
對象中調用
getBlob()
和
getClob()
方法就可以獲得
Blob
對象和
Clob
對象:
Blob blob = rs.getBlob(1);
Clob clob = rs.getClob(2);
?
3
.設置
Lob
對象
Lob
對象可以像普通數據類型一樣作為參數來進行參數賦值,在操作
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);
在一個可更新的結果集中,也可以利用
updateBlob(int,Blob)
和
updateClob(int,Clob)
來更新當前行。
?
4
.改變
Lob
對象的內容
Lob
接口提供了方法讓用戶可以對
Lob
對象的內容進行任意修改:
?
byte[] val = {0,1,2,3,4};
?
Blob data = rs.getBlob(DATA);
int numWritten = data.setBytes(1, val); //
在指定的位置插入數據
PreparedStatement ps = conn.prepareStatement(UPDATE datatab SET data = ?);
ps.setBlob(DATA, data);
ps.executeUpdate();
?
?
?
?Savepoint
?
1
.概述
為了增加對事務的控制,
JDBC
規范
3.0
增加了
Savepoint
這個接口。它代表一個邏輯事務點。在非自動提交模式下,一個事務中可以設置多個
Savepoint
。這樣在回滾時,可以回滾到指定的
Savepoint
,從事務開始到該
Savepoint
之間的操作依然保留著。這就提高了事務處理的粒度,更好地操縱數據。
Savepoint
分為命名的和未命名的兩種。未命名的用系統分配的
ID
作為標識。同時可以通過
DatabaseMetaData.supportsSavepoint()
來判斷
JDBC
驅動程序是否支持
Savepoint
。
?
2
.操作
Savepoint
Savepoint
的操作位于
Conncetion
接口:
Statement stmt = conn.createStatement();
int rows = stmt.executeUpdate(insert into tab1(col) values(' first') ); //
插入第一條數據
Savepoint svpt1 = conn.setSavepoint(SAVEPOINT_1); //
設置一個
Savepoint
rows = stmt.executeUpdate(intert into tab1(col) values('second') ); //
插入第二條數據
……
conn.rollback(svpt1); //
回滾到指定的
Savepoint
……
conn.commit(); //
提交事務
,
真正在數據庫中僅插入了第一條數據
這樣,數據庫中僅增加了第一次插入的那條記錄。注意:在使用
Savepoint
之前,一定要把當前連接設置為非自動提交模式。
在事務提交之后,先前事務中的所有
Savepoint
都自動取消。如果有兩個
Savepoint
,當事務回滾到前面的那個
Savepoint
時,后面的這個
Savepoint
也自動取消。
?
autoGenerated Key
?
在很多數據庫中,插入一條新的記錄時數據庫會為新增的記錄自動產生一個唯一的標識。
JDBC3.0
規范中的
Statement
新增了一個方法:
getGeneratedKeys
,利用這個方法就可以檢索出系統自動為插入的新行所產生的關鍵字。可以傳遞一個
Statement.RETURN_GENERATED_KEYS
標識給
Statement
對象的
execute
、
executeUpdate()
的方法或者
PreparedStatement
對象的一些方法,這樣在執行完這些方法之后就可以檢索新產生的關鍵字。
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)
{
//
檢索新產生的關鍵字的值
……
}
為了檢索方便,用戶也可以為自動產生的關鍵字指定列名或者索引:
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())
{
//
檢索新產生的關鍵字的值
byte[] bs = rs.getBytes(order_id);
}
……
JDBC
驅動程序是否支持自動產生的關鍵字,可以通過
DataBaseMetaData.supportsGetGeneratedKeys
來判斷。
?
?
?
數據源
DataSource
?
數據源是
JDBC 2.0
規范作為擴展包引入的,在
JDBC 3.0
規范中成為核心
API
。數據源不僅能夠從功能上完全取代利用
DriverManager
建立連接的方式,而且具有以下幾點優勢:
(1)
增強了代碼的可移植性;
(2)
方便了代碼的維護;
(3)
利用連接池來提高系統的性能。
?
JDBC
驅動程序提供了對數據源的支持,實現了
javax.sql.DataSource
接口和
java.sql.ConnectionPoolDataSource
接口。用戶通過
javax.sql.DataSource
接口來建立連接。
?
使用數據源來建立連接時,
首先要向
JNDI
注冊一個數據源。在建立連接的時候,首先通過
JNDI
來獲得要使用的數據源:
DataSource ds = (DataSource) ctx.lookup(datasourceName)
;
然后使用這個數據源來建立連接對象:
Connection con = ds.getConnection()
;
該連接同通過
DriverManager
所建立的連接是一樣的。
?
實現
javax.sql.ConnectionPoolDataSource
接口是為了提高系統的性能。通過設置一個連接緩沖區,在其中保持數目較小的物理連接的方式,這個連接緩沖區由大量的并行用戶共享和重新使用,從而避免在每次需要時建立一個新的物理連接,以及當其被釋放時關閉該連接的昂貴操作。該連接池是
JDBC
提供系統性能的一種措施,是在
JDBC
內部實現的,能夠為用戶提供透明的高速緩沖連接訪問。用戶利用數據源來建立連接的應用不需為此做出任何代碼上的變動。
posted on 2006-07-25 08:49
Lizzie 閱讀(2612)
評論(0) 編輯 收藏 所屬分類:
專業積木