1

SpringJDBCDAOで大量のデータを処理しています。DAOは、取得操作が別のスレッドで行われている間(ExecutorServiceを使用)、 take()を使用して制限付きBlockingQueueで動作するオブジェクトに対してイテレーターを直接返します。

このスレッド内では、次の動作が見られます。取得は機能しますが、ResultSetへの特定の呼び出しにより、呼び出しがハングします。これらの呼び出しは

  • isClosed()および
  • isLast()

だがしかし

  • isAfterLast()または
  • isBeforeFirst()または
  • isFirst()

明らかに、最後の要素が何であるかを知る必要があります(イテレーターのhasNext()メソッドでfalseを生成する特別な要素をブロッキングキューに挿入するため)。オブジェクトをBlockingQueueに入れる前に、 ResultSetの行数を調べることで回避できますが、これは少し不器用に感じます。ResultSetを操作するためのスレッドセーフな方法はありますか?

マルチスレッドデータソース(私はC3POのComboPooledDataSourceをテストしました)に切り替えることは役に立たないようです。

注:この問題は、私がここで最初に(誤って)特定したものです

4

2 に答える 2

1

java.sql.ResultSet確かにこれは実際にはjavadocで言及されていませんが、これはスレッドセーフではないと思います。ResultSet異なるスレッドからメソッドを呼び出すと、それらのメソッド呼び出しがハングする場合でも、まったく驚かないでしょう。

別の方法として、検索スレッドをの唯一のユーザーとして、ResultSet行を削除してから、データ自体をにダンプすることをお勧めしますBlockingQueue。次に、結果セットの終わりを検出し、EOFマーカーをキューに入れるのは簡単になります。

非常に大きな結果セットを反復処理するためにJDBCで一般的に推奨されるメカニズムは、のfetchSizeプロパティを使用することですjava.sql.Statementが、これはデータベースとJDBCドライバーに大きく依存します。Oracleドライバがこの設定を尊重していることは知っていますが、他の設定についてはよくわかりません。ドライバーが最初の行を提供する前に結果セット全体をメモリにフェッチする必要があると判断した場合、何をしても、次の行をフェッチしている間は最初の行を処理できません。

于 2009-09-09T12:55:31.293 に答える
1

正しい解決策は、適切なResultSetタイプを設定することです。デフォルトの「TYPE_FORWARD_ONLY」isLast()ではサポートされていません。ResultSetのタイプは、SQL文字列の代わりにPreparedStatementCreatorを使用して設定できます。たとえば、 JdbcTemplateへのquery()呼び出しです。このようなインスタンスは、 PreparedStatementCreatorFactoryを介して取得されます。このようなファクトリでは、ResultSetのタイプ(「TYPE_SCROLL_INSENSITIVE」など)を設定できます。

于 2009-10-01T11:41:45.243 に答える