原文鏈接:http://dev.csdn.net/develop/article/35/article/35/article/34/article/34/article/34/article/34/article/35/35924.shtm
從前面的學習中,我們掌握了通過Statement類及其子類傳遞SQL語句,對數據庫管理系統進行訪問。一般來說,對數據庫的操作大部分都是執行查詢語句。這種語句執行的結果是返回一個ResultSet類的對象。要想把查詢的結果返回給用戶,必須對ResultSet對象進行相關處理。今天,我們就來學習對結果集的處理方法。
按照慣例,讓我們先來看一個例子:
package com.rongji.demo;
import java.sql.*;
public class dataDemo {
public dataDemo() {
}
public static void main(String[] args) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
//建立連接
//第二步是用適當的驅動程序連接到DBMS,看下面的代碼[自行修改您所連接的數據庫相關信息]:
String url = "jdbc:oracle:thin:@192.168.4.45:1521:oemrep";
String username = "ums";
String password = "rongji";
//用url創建連接
Connection con = DriverManager.getConnection(url, username, password);
Statement sta = con.createStatement();
String sql = "select * from rbac_application ";
ResultSet resultSet = sta.executeQuery(sql);
while (resultSet.next()) {
int int_value = resultSet.getInt(1);
String string_value = resultSet.getString(2);
String a = resultSet.getString(3);
String b = resultSet.getString(4);
//從數據庫中以兩種不同的方式取得數據。
System.out.println(int_value + " " + string_value + " " + a + " " +
b);
//將檢索結果在用戶瀏覽器上輸出。
}
//獲取結果集信息
ResultSetMetaData resultSetMD = resultSet.getMetaData();
System.out.println("ColumnCount:" + resultSetMD.getColumnCount());
for (int i = 1; i < resultSetMD.getColumnCount(); i++) {
System.out.println("ColumnName:" + resultSetMD.getColumnName(i) + " " +
"ColumnTypeName:" +
resultSetMD.getColumnTypeName(i));
System.out.println("isReadOnly:" + resultSetMD.isReadOnly(i)
+ " isWriteable:" + resultSetMD.isWritable(i)
+ " isNullable:" + resultSetMD.isNullable(i));
System.out.println("tableName:" + resultSetMD.getTableName(i));
}
//關閉
con.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
1、ResultSet類的基本處理方法
一個ResultSet對象對應着一個由查詢語句返回的一個表,這個表中包含所有的查詢結果,實際上,我們就可以將一個ResultSet對象看成一個表。對ResultSet對象的處理必須逐行進行,而對每一行中的各個列,可以按任何順序進行處理。
ResultSet對象維持一個指向當前行的指針。最初,這個指針指向第一行之前。Result類的next()方法使這個指針向下移動一行。因此,第一次使用next()方法將指針指向結果集的第一行,這時可以對第一行的數據進行處理。處理完畢后,使用next()方法,將指針移向下一行,繼續處理第二行數據。next()方法的返回值是一個boolean型的值,該值若為true, 說明結果集中還存在下一條記錄,並且指針已經成功指向該記錄,可以對其進行處理;若返回值是false,則說明沒有下一行記錄,結果集已經處理完畢。
在對每一行進行處理時,可以對各個列按任意順序進行處理。不過,按從左到右的順序對各列進行處理可以獲得較高的執行效率.ResultSet類的getXXX()方法可以從某一列中獲得檢索結果。其中XXX是JDBC中的Java數據類型,如int, String ,Date等,這與PreparedStatement類和CallableStatement類設置SQL語句參數值相類似。 Sun公司提供的getXXX() API提供兩種方法來指定列名進行檢索:一種是以一個int值作為列的索引,另一種是以一個String對象作為列名來索引。大家可以參照一下上面的例子。
2、獲取結果集的信息
在對數據庫的表結構已經了解的前提下,可以知道返回的結果集中各個列的一些情況,如:列名數據類型等等。有時並不知道結果集中各個列的情況,這時可以使用Resultset類的getMetaData方法來獲取結果集的信息。如上面的例子:
ResultSetMetaData resultSetMD = resultSet.getMetaData();
GetMetaData()方法返回一個ResultSetMetaData類的對象,使用該類的方法,得到許多關於結果集的信息,下面給出幾個常用的方法:
(1) getColumnCount()返回一個int值,指出結果集中的列數。
(2) getTableName(int column)返回一個字符串,指出參數中所代表列的表的名稱。
(3) getColumnLabel(int column)返回一個String對象,該對象是column所指的列的顯示標題。
(4) getColumnName(int column)返回的是該列在數據庫中的名稱。可以把此方法返回的String對象作為Resultset類的getXXX()方法的參數。不過,並沒有太大的實際意義。
(5) getColumnType(int comlumn)返回指定列的SQL數據類型。他的返回值是一個int值。在java.sql.Types類中有關於各種SQL數據類型的定義。
(6) getColumnTypeName(int comlumn)返回指定列的數據類型在數據源中的名稱。他的返回值是一個String對象。
(7) isReadOnly(int column) 返回一個boolean值,指出該列是否是只讀的。
(8) isWriteable(int column) 返回一個boolean值,指出該列是否可寫。
(9) isNullable(int column)返回一個boolean值,指出該列是否允許存入一個NULL 值。
JDBC 概述(五)
5 - ResultSet
5.1 概述
ResultSet 包含符合 SQL 語句中條件的所有行,並且它通過一套 get 方法(這些 get 方法可以訪問當前行中的不同列)提供了對這些行中數據的訪問。ResultSet.next 方法用於移動到 ResultSet 中的下一行,使下一行成為當前行。
結果集一般是一個表,其中有查詢所返回的列標題及相應的值。例如,如果查詢為 SELECT 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 方法。方法 getObject 將任何數據類型返回為 Java Object。當基本數據類型是特定於數據庫的抽象類型或當通用應用程序需要接受任何數據類型時,它是非常有用的。
可使用 ResultSet.getXXX 方法獲取常見的 JDBC 數據類型。
“x”表示該 getXXX 方法可合法地用於獲取給定 JDBC 類型。
“X”表示推薦使用該 getXXX 方法來獲取給定 JDBC 類型。
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 API 具有三個獲取流的方法,分別具有不同的返回值:
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
// 將新填充的緩沖區發送到 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 還是更新計數。
為了適應這些情況,JDBC 提供了一種機制,允許應用程序執行語句,然后處理由結果集和更新計數組成的任意集合。這種機制的原理是首先調用一個完全通用的execute 方法,然后調用另外三個方法,getResultSet、getUpdateCount 和getMoreResults。這些方法允許應用程序一次一個地研究語句結果,並確定給定結
果是 ResultSet 還是更新計數。
用戶不必關閉 ResultSet;當產生它的 Statement 關閉、重新執行或用於從多結果序列中獲取下一個結果時,該 ResultSet 將被 Statement 自動關閉。