JDBCTM 指南:入門5 - ResultSet (轉)
JDBCTM 指南:入門5 - ResultSet (轉)[@more@]5 - ResultSet
本概述是從《JCTM Database Access from TM: A Tutorial and Annotated Reference 》這本書中摘引來的。JavaSoft 目前正在準備這本書。這是一本教程,同時也是 的重要參考手冊,它將作為 Java 系列的組成部份在 1997 年春季由 Addison-Wesley 出版公司出版。
5.1 概述
ResultSet 包含符合 語句中條件的所有行,並且它透過一套 get 方法(這些 get 方法可以訪問當前行中的不同列)提供了對這些行中資料的訪問。ResultSet.next 方法用於移動到 ResultSet 中的下一行,使下一行成為當前行。
結果集一般是一個表,其中有查詢所返回的列標題及相應的值。例如,如果查詢為 a, b, c FROM Table1,則結果集將具有如下形式:
a b c
-------- --------- --------
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA
下面的程式碼段是 SQL 語句的示例。該 SQL 語句將返回行集合,其中列 1 為 int,列 2 為 String,而列 3 則為位元組陣列:
java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (r.next())
{
// 列印當前行的值。
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
5.1.1 行和游標
ResultSet 維護指向其當前資料行的游標。每一次 next 方法,游標向下移動一行。最初它位於第一行之前,因此第一次呼叫 next 將把游標置於第一行上,使它成為當前行。隨著每次呼叫 next 導致游標向下移動一行,按照從上至下的次序獲取 ResultSet 行。
在 ResultSet 或其父輩 Statement 物件關閉之前,游標一直保持有效。
在 SQL 中,結果表的游標是有名字的。如果允許定位或定位刪除,則需要將游標的名字作為引數提供給更新或刪除命令。可透過呼叫方法 getCursorName 獲得游標名。
注意:不是所有的 DBMS 都支援定位更新和刪除。可使用 DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法來檢查特定連線是否支援這些操作。當支援這些操作時,DBMS/必須確保適當鎖定選定行,以使定位更新不會導致更新異常或其它併發問題。
5.1.2 列
方法 getXXX 提供了獲取當前行中某列值的途徑。在每一行內,可按任何次序獲取列值。但為了保證可移植性,應該從左至右獲取列值,並且一次性地讀取列值。
列名或列號可用於標識要從中獲取資料的列。例如,如果 ResultSet 物件 rs 的第二列名為“title”,並將值為字串,則下列任一程式碼將獲取儲存在該列中的值:
String s = rs.getString("title");
String s = rs.getString(2);
注意列是從左至右編號的,並且從列 1 開始。同時,用作 getXXX 方法的輸入的列名不區分大小寫。
提供使用列名這個選項的目的是為了讓在查詢中指定列名的可使用相同的名字作為 getXXX 方法的引數。另一方面,如果 select 語句未指定列名(例如在“select * from table1”中或列是匯出的時),則應該使用列號。這些情況下,使用者將無法確切知道列名。
有些情況下,SQL 查詢返回的結果集中可能有多個列具有相同的名字。如果列名用作 getXXX 方法的引數,則 getXXX 將返回第一個匹配列名的值。因而,如果多個列具有相同的名字,則需要使用列來確保檢索了正確的列值。這時,使用列號要稍微高一些。
關於 ResultSet 中列的資訊,可透過呼叫方法 ResultSet.getMetaData 得到。返回的 ResultSetMetaData 物件將給出其 ResultSet 物件各列的編號、型別和屬性。
如果列名已知,但不知其索引,則可用方法 findColumn 得到其列號。
5.1.3 資料型別和轉換
對於 getXXX 方法,JDBC 驅動程式試圖將基本資料轉換成指定 Java 型別,然後返回適合的 Java 值。例如,如果 getXXX 方法為 getString,而基本資料庫中資料型別為 VARCHAR,則 JDBC 驅動程式將把 VARCHAR 轉換成 Java String。getString 的返回值將為 Java String 物件。
下表顯示了允許用 getXXX 獲取的 JDBC 型別及推薦用它獲取的 JDBC 型別(通用 SQL 型別)。小寫的 x 表示允許 getXXX 方法獲取該資料型別;大寫的 X 表示對該資料型別推薦使用 getXXX 方法。例如,除了 getBytes 和 getBinaryStream 之外的任何 getXXX 方法都可用來獲取 LONGVARCHAR 值,但是推薦根據返回的資料型別使用 getAsciiStream 或 getUnicodeStream 方法。方法 get 將任何資料型別返回為 Java Object。當基本資料型別是特定於資料庫的抽象型別或當通用應用程式需要接受任何資料型別時,它是非常有用的。
可使用 ResultSet.getXXX 方法獲取常見的 JDBC 資料型別。
“x”表示該 getXXX 方法可合法地用於獲取給定 JDBC 型別。
“X”表示推薦使用該 getXXX 方法來獲取給定 JDBC 型別。
T
I
N
Y
I
N
T S
M
A
L
L
I
N
T I
N
T
E
G
E
R B
I
G
N
T R
E
A
L F
L
O
A
T D
O
U
B
L
E D
E
C
I
M
A
L N
U
M
E
R
I
C B
I
T C
H
A
R V
A
R
C
H
A
R
L
O
N
G
V
A
R
C
H
A
R B
I
N
A
R
Y V
A
R
B
I
N
A
R
Y L
O
N
G
V
A
R
B
I
N
A
R
Y D
A
T
E T
I
M
E T
I
M
E
S
T
A
M
P
getByte X x x x x x x x x x x x x
getShort x X x x x x x x x x x x x
getInt x x X x x x x x x x x x x
getLong x x x X x x x x x x x x x
getFloat x x x x X x x x x x x x x
getDouble x x x x x X X x x x x x x
getBigDecimal x x x x x x x X X x x x x
getBoolean x x x x x x x x x X x x x
getString x x x x x x x x x x X X x x x x x x x
getBytes X X x
getDate x x x X x
getTime x x x X x
getTimestamp x x x x X
getAsciiStream x x X x x x
getUnicodeStream x x X x x x
getBinaryStream x x X
getObject x x x x x x x x x x x x x x x x x x x
5.1.4 對非常大的行值使用流
ResultSet 可以獲取任意大的 LONGVARBINARY 或 LONGVARCHAR 資料。方法 getBytes 和 getString 將資料返回為大的塊(最大為 Statement.getMaxFieldSize 的返回值)。但是,以較小的固定塊獲取非常大的資料可能會更方便,而這可透過讓 ResultSet 類返回 java.io.Input 流來完成。從該流中可分塊讀取資料。注意:必須立即訪問這些流,因為在下一次對 ResultSet 呼叫 getXXX 時它們將自動關閉(這是由於基本實現對大塊資料訪問有限制)。
JDBC 具有三個獲取流的方法,分別具有不同的返回值:
getBinaryStream 返回只提供資料庫原位元組而不進行任何轉換的流。
getAsciiStream 返回提供單位元組 ASCII 字元的流。
getUnicodeStream 返回提供雙位元組 Unicode 字元的流。
注意:它不同於 Java 流,後者返回無型別位元組並可(例如)通用於 ASCII 和 Unicode 字元。
下列程式碼演示了 getAsciiStream 的用法:
java.sql.Statement stmt = con.createStatement();
ResultSet r = stmt.executeQuery("SELECT x FROM Table2");
// 現在以 4K 塊大小獲取列 1 結果:
byte buff = new byte[4096];
while (r.next()) {
Java.io.InputStream fin = r.getAsciiStream(1);
for (;;) {
int size = fin.read(buff);
if (size == -1) { // 到達流末尾
break;
}
// 將新填充的緩衝區傳送到 ASCII 輸出流:
output.write(buff, 0, size);
}
}
5.1.5 NULL 結果值
要確定給定結果值是否是 JDBC NULL,必須先讀取該列,然後使用 ResultSet.wasNull 方法檢查該次讀取是否返回 JDBC NULL。
當使用 ResultSet.getXXX 方法讀取 JDBC NULL 時,方法 wasNull 將返回下列值之一:
Java null 值:對於返回 Java 物件的 getXXX 方法(例如 getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream、getUnicodeStream、getBinaryStream、getObject 等)。
零值:對於 getByte、getShort、getInt、getLong、getFloat 和 getDouble。
false 值:對於 getBoolean。
5.1.6 可選結果集或多結果集
通常使用 executeQuery(它返回單個 ResultSet)或 executeUpdate(它可用於任何資料庫修改語句,並返回更新行數)可執行 SQL 語句。但有些情況下,應用程式在執行語句之前不知道該語句是否返回結果集。此外,有些已可能返回幾個不同的結果集和/或更新計數。
為了適應這些情況,JDBC 提供了一種機制,允許應用程式執行語句,然後處理由結果集和更新計陣列成的任意集合。這種機制的原理是首先呼叫一個完全通用的 execute 方法,然後呼叫另外三個方法,getResultSet、getUpdateCount 和 getMoreResults。這些方法允許應用程式一次一個地研究語句結果,並確定給定結果是 ResultSet 還是更新計數。
使用者不必關閉 ResultSet;當產生它的 Statement 關閉、重新執行或用於從多結果序列中獲取下一個結果時,該 ResultSet 將被 Statement 自動關閉。
本概述是從《JCTM Database Access from TM: A Tutorial and Annotated Reference 》這本書中摘引來的。JavaSoft 目前正在準備這本書。這是一本教程,同時也是 的重要參考手冊,它將作為 Java 系列的組成部份在 1997 年春季由 Addison-Wesley 出版公司出版。
5.1 概述
ResultSet 包含符合 語句中條件的所有行,並且它透過一套 get 方法(這些 get 方法可以訪問當前行中的不同列)提供了對這些行中資料的訪問。ResultSet.next 方法用於移動到 ResultSet 中的下一行,使下一行成為當前行。
結果集一般是一個表,其中有查詢所返回的列標題及相應的值。例如,如果查詢為 a, b, c FROM Table1,則結果集將具有如下形式:
a b c
-------- --------- --------
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA
下面的程式碼段是 SQL 語句的示例。該 SQL 語句將返回行集合,其中列 1 為 int,列 2 為 String,而列 3 則為位元組陣列:
java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (r.next())
{
// 列印當前行的值。
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
5.1.1 行和游標
ResultSet 維護指向其當前資料行的游標。每一次 next 方法,游標向下移動一行。最初它位於第一行之前,因此第一次呼叫 next 將把游標置於第一行上,使它成為當前行。隨著每次呼叫 next 導致游標向下移動一行,按照從上至下的次序獲取 ResultSet 行。
在 ResultSet 或其父輩 Statement 物件關閉之前,游標一直保持有效。
在 SQL 中,結果表的游標是有名字的。如果允許定位或定位刪除,則需要將游標的名字作為引數提供給更新或刪除命令。可透過呼叫方法 getCursorName 獲得游標名。
注意:不是所有的 DBMS 都支援定位更新和刪除。可使用 DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法來檢查特定連線是否支援這些操作。當支援這些操作時,DBMS/必須確保適當鎖定選定行,以使定位更新不會導致更新異常或其它併發問題。
5.1.2 列
方法 getXXX 提供了獲取當前行中某列值的途徑。在每一行內,可按任何次序獲取列值。但為了保證可移植性,應該從左至右獲取列值,並且一次性地讀取列值。
列名或列號可用於標識要從中獲取資料的列。例如,如果 ResultSet 物件 rs 的第二列名為“title”,並將值為字串,則下列任一程式碼將獲取儲存在該列中的值:
String s = rs.getString("title");
String s = rs.getString(2);
注意列是從左至右編號的,並且從列 1 開始。同時,用作 getXXX 方法的輸入的列名不區分大小寫。
提供使用列名這個選項的目的是為了讓在查詢中指定列名的可使用相同的名字作為 getXXX 方法的引數。另一方面,如果 select 語句未指定列名(例如在“select * from table1”中或列是匯出的時),則應該使用列號。這些情況下,使用者將無法確切知道列名。
有些情況下,SQL 查詢返回的結果集中可能有多個列具有相同的名字。如果列名用作 getXXX 方法的引數,則 getXXX 將返回第一個匹配列名的值。因而,如果多個列具有相同的名字,則需要使用列來確保檢索了正確的列值。這時,使用列號要稍微高一些。
關於 ResultSet 中列的資訊,可透過呼叫方法 ResultSet.getMetaData 得到。返回的 ResultSetMetaData 物件將給出其 ResultSet 物件各列的編號、型別和屬性。
如果列名已知,但不知其索引,則可用方法 findColumn 得到其列號。
5.1.3 資料型別和轉換
對於 getXXX 方法,JDBC 驅動程式試圖將基本資料轉換成指定 Java 型別,然後返回適合的 Java 值。例如,如果 getXXX 方法為 getString,而基本資料庫中資料型別為 VARCHAR,則 JDBC 驅動程式將把 VARCHAR 轉換成 Java String。getString 的返回值將為 Java String 物件。
下表顯示了允許用 getXXX 獲取的 JDBC 型別及推薦用它獲取的 JDBC 型別(通用 SQL 型別)。小寫的 x 表示允許 getXXX 方法獲取該資料型別;大寫的 X 表示對該資料型別推薦使用 getXXX 方法。例如,除了 getBytes 和 getBinaryStream 之外的任何 getXXX 方法都可用來獲取 LONGVARCHAR 值,但是推薦根據返回的資料型別使用 getAsciiStream 或 getUnicodeStream 方法。方法 get 將任何資料型別返回為 Java Object。當基本資料型別是特定於資料庫的抽象型別或當通用應用程式需要接受任何資料型別時,它是非常有用的。
可使用 ResultSet.getXXX 方法獲取常見的 JDBC 資料型別。
“x”表示該 getXXX 方法可合法地用於獲取給定 JDBC 型別。
“X”表示推薦使用該 getXXX 方法來獲取給定 JDBC 型別。
T
I
N
Y
I
N
T S
M
A
L
L
I
N
T I
N
T
E
G
E
R B
I
G
N
T R
E
A
L F
L
O
A
T D
O
U
B
L
E D
E
C
I
M
A
L N
U
M
E
R
I
C B
I
T C
H
A
R V
A
R
C
H
A
R
L
O
N
G
V
A
R
C
H
A
R B
I
N
A
R
Y V
A
R
B
I
N
A
R
Y L
O
N
G
V
A
R
B
I
N
A
R
Y D
A
T
E T
I
M
E T
I
M
E
S
T
A
M
P
getByte X x x x x x x x x x x x x
getShort x X x x x x x x x x x x x
getInt x x X x x x x x x x x x x
getLong x x x X x x x x x x x x x
getFloat x x x x X x x x x x x x x
getDouble x x x x x X X x x x x x x
getBigDecimal x x x x x x x X X x x x x
getBoolean x x x x x x x x x X x x x
getString x x x x x x x x x x X X x x x x x x x
getBytes X X x
getDate x x x X x
getTime x x x X x
getTimestamp x x x x X
getAsciiStream x x X x x x
getUnicodeStream x x X x x x
getBinaryStream x x X
getObject x x x x x x x x x x x x x x x x x x x
5.1.4 對非常大的行值使用流
ResultSet 可以獲取任意大的 LONGVARBINARY 或 LONGVARCHAR 資料。方法 getBytes 和 getString 將資料返回為大的塊(最大為 Statement.getMaxFieldSize 的返回值)。但是,以較小的固定塊獲取非常大的資料可能會更方便,而這可透過讓 ResultSet 類返回 java.io.Input 流來完成。從該流中可分塊讀取資料。注意:必須立即訪問這些流,因為在下一次對 ResultSet 呼叫 getXXX 時它們將自動關閉(這是由於基本實現對大塊資料訪問有限制)。
JDBC 具有三個獲取流的方法,分別具有不同的返回值:
getBinaryStream 返回只提供資料庫原位元組而不進行任何轉換的流。
getAsciiStream 返回提供單位元組 ASCII 字元的流。
getUnicodeStream 返回提供雙位元組 Unicode 字元的流。
注意:它不同於 Java 流,後者返回無型別位元組並可(例如)通用於 ASCII 和 Unicode 字元。
下列程式碼演示了 getAsciiStream 的用法:
java.sql.Statement stmt = con.createStatement();
ResultSet r = stmt.executeQuery("SELECT x FROM Table2");
// 現在以 4K 塊大小獲取列 1 結果:
byte buff = new byte[4096];
while (r.next()) {
Java.io.InputStream fin = r.getAsciiStream(1);
for (;;) {
int size = fin.read(buff);
if (size == -1) { // 到達流末尾
break;
}
// 將新填充的緩衝區傳送到 ASCII 輸出流:
output.write(buff, 0, size);
}
}
5.1.5 NULL 結果值
要確定給定結果值是否是 JDBC NULL,必須先讀取該列,然後使用 ResultSet.wasNull 方法檢查該次讀取是否返回 JDBC NULL。
當使用 ResultSet.getXXX 方法讀取 JDBC NULL 時,方法 wasNull 將返回下列值之一:
Java null 值:對於返回 Java 物件的 getXXX 方法(例如 getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream、getUnicodeStream、getBinaryStream、getObject 等)。
零值:對於 getByte、getShort、getInt、getLong、getFloat 和 getDouble。
false 值:對於 getBoolean。
5.1.6 可選結果集或多結果集
通常使用 executeQuery(它返回單個 ResultSet)或 executeUpdate(它可用於任何資料庫修改語句,並返回更新行數)可執行 SQL 語句。但有些情況下,應用程式在執行語句之前不知道該語句是否返回結果集。此外,有些已可能返回幾個不同的結果集和/或更新計數。
為了適應這些情況,JDBC 提供了一種機制,允許應用程式執行語句,然後處理由結果集和更新計陣列成的任意集合。這種機制的原理是首先呼叫一個完全通用的 execute 方法,然後呼叫另外三個方法,getResultSet、getUpdateCount 和 getMoreResults。這些方法允許應用程式一次一個地研究語句結果,並確定給定結果是 ResultSet 還是更新計數。
使用者不必關閉 ResultSet;當產生它的 Statement 關閉、重新執行或用於從多結果序列中獲取下一個結果時,該 ResultSet 將被 Statement 自動關閉。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-989812/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JDBCTM 指南:入門4 - Statement (轉)JDBC
- JDBCTM 指南:入門3 - DriverManager (轉)JDBC
- JDBCTM 指南:入門2 - 連線 (轉)JDBC
- JDBCTM 指南:入門7 - CallableStatement (轉)JDBC
- HTML5新手入門指南HTML
- 給萌新HTML5 入門指南HTML
- 給萌新HTML5 入門指南(二)HTML
- XML入門指南(4)XML元素(轉)XML
- Red Hat Linux 入門指南!(轉)Linux
- wsad5入門 (轉)
- Vue.js新手入門指南[轉載]Vue.js
- Tomcat 4/JSP入門指南(轉)TomcatJS
- 程式設計“初學者”入門指南 (轉)程式設計
- XML入門指南(18)XML行為(轉)XML
- XML入門指南(15)XML編碼(轉)XML
- XML入門指南(6)XML確認(轉)XML
- XML入門指南(3)XML語法(轉)XML
- XML入門指南(1)XML簡介(轉)XML
- J2EE入門(5) (轉)
- Zookeeper入門指南
- CPack 入門指南
- Docker 入門指南Docker
- numpy入門指南
- EOS 入門指南
- Vue 入門指南Vue
- RabbitMQ入門指南MQ
- Nginx入門指南Nginx
- Vagrant 入門指南
- React 入門指南React
- Flask 入門指南Flask
- gulp入門指南
- OSWorkFlow入門指南
- CouchDB 入門指南
- RxJava入門指南RxJava
- ODA入門指南
- MySQL 入門指南MySql
- Markdown入門指南
- JDBC TM入門指南6--Parepared Statement (轉)JDBC