| 目次 | 前の項目 | 次の項目 | JDBCTM ガイド: 使用の開始 |
ResultSet は、SQL 文の条件を満たすすべての行を含んでおり、現在の行のさまざまな列にアクセスできる一連の get メソッドによって、これらの行のデータにアクセスする手段を提供します。ResultSet.next メソッドは、ResultSet の次行に移動するために使用され、次行が現在行になるようにします。
ResultSet の一般的な形式は、列の見出しとクエリーの結果に対応する値から成るテーブルです。たとえば、クエリーが SELECT a, b, c FROM Table1であれば、結果は次のような形式になります。
a b c
-------- --------- --------
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA
次のコード断片は、列 1 を int、列 2 を String、そして列 3 をバイトの配列とする行のコレクションを戻す SQL 文の実行例です。
java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (r.next())
{
// print the values for the current row.
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
ResultSet は、現在行のデータを指し示すカーソルを維持します。カーソルは next メソッドが呼び出されるたびに 1 行ずつ下に移動します。カーソルは、最初は 1 行目の前に位置するので、next の一度目の呼び出しでは、カーソルが 1 行目に位置し、この行が現在行になります。ResultSet 行は、最上行から順次下に検索され、次の next の呼び出しのたびにカーソルが 1 行ずつ下に移動します。
カーソルは、ResultSet オブジェクトまたはその上位の Statement オブジェクトが閉じられるまで有効になっています。
SQL では、結果テーブルのカーソルに名前が付けられます。データベースでカーソル位置での更新または削除が可能な場合には、そのカーソルの名前を更新コマンドまたは削除コマンドとして与える必要があります。この名前を取得するには、メソッド getCursorName を呼び出します。
すべての DBMS が、カーソル位置での更新または削除をサポートするとは限らないことに注意してください。DatabaseMetaData.supportsPositionedDelete および supportsPositionedUpdate メソッドを使用して、カーソル位置での更新または削除が、ある接続でサポートされているかどうかを検出できます。これらの操作がサポートされている場合、カーソル位置での更新または削除の際に、複数の処理から同じ行を更新することがないように、DBMS ドライバは、選択行が適切にロックされているかを確認する必要があります。
getXXX メソッドは、現在行から列を検索する手段を提供します。各行で列値を任意の順序で検索できますが、移植性を最大にするため、値は左から右に検索し、列値の読み取りを一度だけにします。
データを取り出す元の列の指定には、列名または列番号のどちらでも使用できます。たとえば、ResultSet オブジェクト rs の 2 列目は "title" という名前が付けられ、値を文字列として格納する場合は、次のどちらでもその列に格納された値を取り出します。
String s = rs.getString("title");
String s = rs.getString(2);
列には、左から右へと列 1 から始まる番号が付けられていることに注意してください。また、getXXX メソッドへの入力に使用される列名は大文字小文字を識別しません。
クエリーで列名を指定したユーザが getXXX メソッドの引数として同じ名前を使用できるように、列名を使用するオプションが提供されました。一方、SELECT 文に列名が指定されていない場合 ("select * from table1" であるか、または列が導き出された列である場合など) には、列番号を使用すべきです。そのような場合は、ユーザが列名を確実に知る方法はありません。
場合によっては、SQL 文の結果が同名の列を複数持つ結果のセットを返すこともあり得ます。getXXX メソッドを指すパラメータとして、列名が使用されている場合には、 getXXX は最初に一致する列名の値を返します。したがって、同名の列が複数ある場合は、正しい列値を取り出したかを確認するために列の添字を使用する必要があります。また、列番号を使用した方が多少効率的であると言えます。
メソッド ResultSet.getMetaData を呼び出すと、ResultSet の中の列に関する情報を入手できます。返される ResultSetMetaData オブジェクトには、その ResultSet オブジェクトの列の番号、型、およびプロパティがついています。
列の名前が既知であるがその添字がわからない場合は、メソッド findColumn を使用して列番号を検索することができます。
getXXX メソッドでは、JDBC ドライバは基礎データを指定の Java の型に変換しようと試みてから、適切な Java 値を返します。たとえば、getXXX メソッドが getString であり、基礎のデータベースのデータの型が VARCHAR である場合、JDBC ドライバは VARCHAR を Java String に変換します。getString の返却値は Java String オブジェクトになります。
次の表は、 getXXX メソッドでどの JDBC 型を取り出すことができるか、およびこのメソッドでの取り出しには、どの JDBC 型 (汎用的な SQL 型) が推奨されているかを示しています。小文字の x は、特定のデータ型の正当な getXXX メソッドを示し、大文字の X は、データ型の推奨 getXXX メソッドを示します。たとえば、LONGVARCHAR の値を取り出すには、 getBytes または getBinaryStream を除く任意の getXXX メソッドを使用できますが、どのデータ型が返されるかによって、getAsciiStream または getUnicodeStream が推奨されています。メソッド getObject は、どんなデータ型でも 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 |
ResultSet では、大きな LONGVARBINARY または LONGVARCHAR データを任意に検索することが可能になります。メソッド getBytes と getString は、1 つの大きなかたまりのようなデータを返します (Statement.getMaxFieldSize の戻り値によって課された限界まで)。しかし、大きなデータを小さい固定サイズに分割して取得することもできます。これを行うには、データをかたまりで読み取ることができる ResultSet クラスの戻り値 java.io.Input ストリームが必要です。このストリームは、次の ResultSet の getXXX 呼び出しで自動的に閉じられてしまうため、すぐにアクセスする必要があることに注意してください。この動作は、大きなかたまりのアクセスでの基本的な実装の制約によって義務付けられています。
JDBC API にはストリームを取得する個別メソッドが 3 つあり、それぞれが異なった戻り値を返します。
getBinaryStream は、データベースから単に行バイト数をまったく変換しないまま返す
getAsciiStream は、1 バイトの ASCII 文字を提供するストリームを返す
getUnicodeStream は、2 バイトの Unicode 文字を提供するストリームを返す
次のコードは、getAsciiStream の使用例を示しています。
java.sql.Statement stmt = con.createStatement();
ResultSet r = stmt.executeQuery("SELECT x FROM Table2");
// Now retrieve the column 1 results in 4 K chunks:
byte buff = new byte[4096];
while (r.next()) {
Java.io.InputStream fin = r.getAsciiStream(1);
for (;;) {
int size = fin.read(buff);
if (size == -1) { // at end of stream
break;
}
// Send the newly-filled buffer to some ASCII output stream:
output.write(buff, 0, size);
}
}
JDBC NULL であるかどうかを判別するため、まず列を読み取り、次に ResultSet.wasNull メソッドを使用して、読み取った値が JDBC NULL を返したかどうかを判断しなければなりません。
ResultSet.getXXX メソッドの 1 つを使用して JDBC NULL を読み取ったときは、メソッド wasNull は次の値の 1 つを返します。
getXXX メソッドの Java null 値 (getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream, getUnicodeStream, getBinaryStream、getObject などのメソッド)
getByte、getShort、getInt、getLong、getFloat、および getDouble のゼロ値
getBoolean の false の値
executeQuery (単一の ResultSet を返す) または executeUpdate (どんな種類のデータベース UPDATE 文にも使用でき、更新された行のカウントを返す) のどちらかを使用して実行されます。しかし、状況によっては、アプリケーションが与えられた文が実行されるまで結果のセットを返すかどうかが、不明である場合があります。さらに、ストアドプロシージャによっては、いくつかの異なる結果のセットまたは更新カウント、あるいはこの両方を返すものがあります。
これらの状況に対処するため、JDBC は、アプリケーションが文を実行し、さらに結果のセットおよび更新カウントの任意の収集結果を処理することができるような機構を提供します。この機構は、最初は完全に汎用的な execute メソッドの呼び出し、続いて他の 3 つのメソッド、すなわち getResultSet、getUpdateCount、および getMoreResults の呼び出しに基づいています。これらのメソッドでは、アプリケーションが文の結果を一度に 1 つずつ探し出し、与えられた結果が ResultSet または更新カウントのどちらであるかを判別することができます。
ResultSet を閉じるには、何もする必要がありません。これは、Statement が閉じられるとき、再実行されるとき、または一連の複数結果から次の結果を検索するために使用されるときに、ResultSet を生成した Statement が、ResultSet を自動的に閉じるからです。