S-JIS[2023-10-07]
TsurugiのTsubakur/Javao(Java通信ライブラリー)のSqlClientのResultSetのメモ。
Tsubakur/JavaoのResultSetは、select結果を取得するクラス。
ResultSetはTransactionのexecuteQueryメソッド(のFutureResponse)から
取得する。
ResultSetから各レコード・各カラムの値を取得する。
ResultSetは使い終わったらクローズする必要がある。
import java.util.List; import java.util.concurrent.TimeUnit; import com.tsurugidb.sql.proto.SqlCommon.Column; import com.tsurugidb.tsubakuro.sql.ResultSet;
// トランザクション開始
var option = TransactionOption.newBuilder().setType(TransactionType.SHORT).build();
try (Transaction transaction = sqlClient.createTransaction(option).await(3, TimeUnit.SECONDS)) {
// select実行
String sql = "select * from test";
try (ResultSet rs = transaction.executeQuery(sql).await(3, TimeUnit.SECONDS)) {
List<? extends Column> columnList = rs.getMetadata().getColumns();
while (rs.nextRow()) {
for (int i = 0; rs.nextColumn(); i++) {
Column column = columnList.get(i);
if (rs.isNull()) {
System.out.printf("%s: null%n", column.getName());
} else {
switch (column.getAtomType()) {
case INT4: // int
int int4 = rs.fetchInt4Value();
System.out.printf("%s: %d%n", column.getName(), int4);
break;
case INT8: // bigint
long int8 = rs.fetchInt8Value();
System.out.printf("%s: %d%n", column.getName(), int8);
break;
case CHARACTER: // charやvarchar
String string = rs.fetchCharacterValue();
System.out.printf("%s: %s%n", column.getName(), string);
break;
default:
throw new UnsupportedOperationException(column.toString());
}
}
}
}
}
// selectのみのトランザクションでも、必ずコミットする
transaction.commit().await(10, TimeUnit.SECONDS);
}
selectの実行結果(複数レコード)を取得するには、まず、ResultSetのnextRowメソッドを呼び出す。
trueが返るとレコードが有るので、trueである間ループする。
次に、ResultSetのnextColumnメソッドを呼び出す。
trueが返るとカラムが有るので、trueである間ループする。
これによりselect結果レコードのカラムを移動していく。
カラムの値がnullかどうかは、ResultSetのisNullメソッドで判定する。
null以外の場合、カラムの値はfetch系メソッドで取得する。(なぜgetというメソッド名でないかと言うと、一度しか取得できないから)
fetch系メソッドは、カラムのデータ型に一致しているメソッドを使用する必要がある。
カラムのデータ型やカラム名は、ResultSetのgetMetadataメソッドで取得できる。
select文でカラムに名前が付けられていない場合、カラム名はnullになる。(Tsurugiサーバー側で暗黙の名前を付けてくれない)
ResultSetから汎用的に読もうとすると、メタデータからデータ型をチェックする必要があり、全てのデータ型に対応する必要が生じてswitch文が長くなってしまうorz
(なお、Iceaxeはこういったことを行ってくれるので、Iceaxeを使う方が便利)
select結果の各カラムのデータ型が事前に分かっているのなら、メタデータからデータ型を取得する必要は無い。
// select実行
String sql = "select pk /*int primary key*/, value /*bigint*/ from test";
try (ResultSet rs = transaction.executeQuery(sql).await(3, TimeUnit.SECONDS)) {
while (rs.nextRow()) {
rs.nextColumn();
int pk = rs.fetchInt4Value();
rs.nextColumn();
Long value = rs.isNull() ? null : rs.fetchInt8Value();
System.out.printf("%d, %d%n", pk, value);
}
}
select文からプログラムを生成するツールやフレームワークなら、こういったソースコードを生成するのが良さそう。