- ベストアンサー
dbからデータを取得する際のfetch結果のjavaへの取り出し方法
- dbからデータを取得する際、SQLのfetch結果をJavaで取得する方法を教えてください。
- SELECT文で通常の取得方法はわかるが、fetchを使った場合、カーソルに関係して処理が変わってくるため、具体的な記述方法を教えてください。
- PostgresqlMyAdminではfetch結果を表示することができないため、commitする前に取得する方法を知りたいです。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
「fetch forward 3 from cursor_name」というSQLはPostgreSQLの拡張なので、 PostgreSQLのJDBCドライバであれば Statement#setFetchSize()で指定行数を取得することは実行可能のようです。 (根拠 → http://www.postgresql.jp/document/pg743doc/html/jdbc-query.html#AEN24290) ただし未検証の上、PostgreSQL7.4.3のドキュメントなので断言できませんが。 前のレスで、「ResultSetオブジェクトに・・・結果をセットしています」といいましたが 実際には 1.データベースよりデータを取得してメモリ上にデータキャッシュ 2.仮想テーブルのキャッシュデータへポインタをあてる という状態となります。 (下記が参考になると思います http://www.atmarkit.co.jp/fjava/rensai2/jspservlet10/jspsevlet10_1.html) Statement#setFetchSize()でできることは この仮想テーブルへのデータキャッシュについて、 デフォルトは全件とってきて乗せるところを 指定行数ずつ乗せるよう変えられるのだと思います。 またキャッシュ範囲がrs.next() で超えた場合、 次のデータ取り出しを自動に行います。 (参考: http://inoccu.net/blog/tag/seaser2/) そのためrs.next()でループすると3件どころか全部出てくるのだと考えられます。 (DB2で検証したところそうなりました) ただしドキュメントを読む限り、 PostgreSQLのJDBCドライバでは違う挙動、 すなわちStatement#setFetchSize()で指定した行数だけ取得するみたいです。 ただしそれはStatement#setMaxRows()を指定したときと同じ動作だと思いますが。 >また、どうしても分りにくいのですが、 >「ResultSet オブジェクトでより多くの行が必要なときにデータベースから取り出す必要がある行数」 >= つまり、これはdbからとりだすデータがselect結果より多い時と少ない時では、多い時に有効なのでしょうか? setFetchSize()を使う目的は、パフォーマンスチューニングです。 たとえばデータベースのレコードが100万件もあるような膨大なデータを扱うとき、 この100万件を一気にメモリへキャッシュすることは 大きなパフォーマンス劣化とメモリ資源消費の懸念があります。 メモリの積載が少ないPCでは、エラーが発生してしまうでしょう。 これらを補うためsetFetchSize()でフェッチ件数を調整し、 パフォーマンスの向上を図ることが可能になります。
その他の回答 (2)
- mako_sea
- ベストアンサー率47% (62/130)
No1で示したAPIは、 ResultSetオブジェクトには3件ずつ フェッチでDBアクセスして結果をセットしています。 しかしnext()で呼び出す時点では全件セットし終わった後になります。 質問者さんは3件セット毎に 結果セットの編集もしくは参照がしたいのですよね。 そういう場合には適してないようです。 どうもすみませんでした。 データベース製品によって、ベンダーの提供しているSQLドライバで フェッチカーソルの扱いも違いがあるようです。 質問者さんの使用しているデータベースの製品名とバージョンはなんでしょう?
補足
ありがとうございます。 使用DBは、Postgresqlでバージョンは、PostgreSQL Database Server 8.1です。 > ResultSetオブジェクトには3件ずつ フェッチでDBアクセスして結果をセットしています。 というと、3件づつのかたまりで順にResultSetに渡されていると考えていいのでしょうか? fetchSize()を使用しなければ、全てが順にResultSetに渡される。 javaの、StatementのsetFetchSize(),getFetchSize()を見てみたのですが、 「 この Statement で作成された ResultSet オブジェクトでより多くの行が必要なときにデータベースから取り出す必要がある行数についてのヒントを JDBC ドライバに提供します。指定された値が 0 の場合、ヒントは無視されます。デフォルト値はゼロです。 」 これを見ると、dbからとりだすデータの行を指定できると言ってはいるのでしょうか? fetchSizeを指定しなかったら、select結果全てがとりだされる、というわけではないのでしょうか? また、どうしても分りにくいのですが、 「ResultSet オブジェクトでより多くの行が必要なときにデータベースから取り出す必要がある行数」 = つまり、これはdbからとりだすデータがselect結果より多い時と少ない時では、多い時に有効なのでしょうか? よろしくお願いします。
- mako_sea
- ベストアンサー率47% (62/130)
フェッチで結果セットを3行ずつResultSetにのせることは 次のコーディングで可能です Statement stmt = con.createStatement(); stmt.setFetchSize(3); ResultSet rs = stmt.executeQuery("実行SQL"); 参考URLで解説がありましたので一読してみてください。
補足
ありがとうございます。 参考URL共に、確認してみました。 その場合どうしても分らないのですが、 rsの結果を3行とりだすには、 while(rs.next()){}を使用すると、fetchSizeに関係なく、全部とりだされてしまうのですが、 この場合、3行だけとりだすにはどうすべきなのでしょうか? stmt.getFetchSize();では、3行とれているので、このメソッドを使用して処理するのかと思ったのですが。 よろしくお願いします。
お礼
ありがとうございます。 > setFetchSize()を使う目的は、パフォーマンスチューニングです。 たとえばデータベースのレコードが100万件もあるような膨大なデータを扱うとき、 この100万件を一気にメモリへキャッシュすることは 大きなパフォーマンス劣化とメモリ資源消費の懸念があります。 メモリの積載が少ないPCでは、エラーが発生してしまうでしょう。 これらを補うためsetFetchSize()でフェッチ件数を調整し、 パフォーマンスの向上を図ることが可能になります。 これについては、fetchSize()で件数を决めると、確かに、パフォーマンス上いいようなきがします。。。 その後色いろ試したところ、fetchSize()を指定し、それをwhileでループさせれば、fetchSize分とりだせるようになったのですが、、、 時間があきすぎたので、再度while文で質問するので、よければ回答お願いします。 ありがとうございました、とても参考になりました。。。