ResultSet 封裝 SQL 查詢結果集,維護游標指向當前資料列,透過 getXXX 方法存取欄位值。next() 移動游標至下一列,初始位於第一列之前。
範例查詢 SELECT a, b, c FROM Table1 產生表格:
a b c
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA
遍歷代碼範例:
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) {
int i = rs.getInt("a");
String s = rs.getString("b");
float f = rs.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
next() 移至第一列。ResultSet 或父 Statement 關閉前持續有效。getCursorName())。非所有 DBMS 支援,可用 DatabaseMetaData.supportsPositionedDelete/Update 檢查。getXXX 可任意順序存取欄位,但**為可移植性建議從左至右、一次性讀取**。rs.getString("title") ≡ rs.getString(2)getXXX(String) 回傳第一個匹配值,**需用索引確保正確性**,效率亦略高。ResultSetMetaData meta = rs.getMetaData() 取得欄位數、型別、屬性。findColumn(String) 由名稱查索引。JDBC 驅動程式嘗試將資料庫型別轉換為指定 Java 型別。下表標示合法 (x) 與推薦 (X) 組合:
| JDBC 型別 → | CHAR | VARCHAR | LONGVARCHAR | NUMERIC | DECIMAL | BIT | TINYINT | SMALLINT | INTEGER | BIGINT | REAL | FLOAT | DOUBLE | BINARY | VARBINARY | LONGVARBINARY | DATE | TIME | TIMESTAMP |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
getString | X | X | x | x | x | 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 | x | x | x | x | x | |
getLong | x | x | x | x | x | 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 | x | x | x | x | x | |
getBytes | X | X | x | ||||||||||||||||
getDate | X | x | x | ||||||||||||||||
getTimestamp | x | x | X | ||||||||||||||||
getAsciiStream | 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 |
getObject 通用性最強,適用資料庫特有抽象型別或通用應用。
getBytes/getString 受限於 Statement.getMaxFieldSize()。大數據建議用流分塊讀取:
getBinaryStream():原始位元組流getAsciiStream():單位元組 ASCII 字元流getUnicodeStream():雙位元組 Unicode 字元流關鍵限制:流**必須立即讀取**,下一次 getXXX 呼叫會自動關閉前一流 (底層實作限制)。
範例:以 4KB 緩衝區讀取 ASCII 流:
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT x FROM Table2");
byte[] buff = new byte[4096];
while (rs.next()) {
InputStream is = rs.getAsciiStream(1);
int size;
while ((size = is.read(buff)) != -1) {
output.write(buff, 0, size); // 輸出至 ASCII 目的地
}
}
**必須先讀取欄位,再呼叫 wasNull() 判斷是否為 SQL NULL**:
getString、getObject 等) → nullgetInt、getDouble 等) → 0getBoolean → false預設用 executeQuery (單一 ResultSet) 或 executeUpdate (更新計數)。但預存程序可能回傳多個結果集/更新計數,或執行前不知是否有結果集。
通用機制:execute() + 三輔助方法:
getResultSet():取得當前結果集getUpdateCount():取得當前更新計數getMoreResults():移至下一結果,回傳 true 表示有結果集,false 表示有更新計數或無結果ResultSet 隨產生它的 Statement 關閉、重新執行、或取得下一結果時自動關閉,無需手動關閉。
掌握 ResultSet 游標模型、型別轉換規則、大數據流處理與 NULL 語意,是 JDBC 高效存取關係式資料的基石。多結果集機制雖少用,但支援複雜預存程序不可或缺。