2009-03-06 12 views
1

PreparedStatementを使用して、MS SQLデータベースからデータのサブセットを選択しています。 結果セットを反復処理しながら、行を更新する必要があります。現時点では私はこのようなものを使用します。preparedStatement selectの使用中にデータベースを更新する

prepStatement = con.prepareStatement(
        selectQuery, 
        ResultSet.TYPE_FORWARD_ONLY, 
        ResultSet.CONCUR_UPDATABLE); 


rs = prepStatement.executeQuery(); 

while(rs.next){ 
rs.updateInt("number", 20) 
rs.updateRow(); 
} 

データベースが正しい値で更新が、私は次の例外を取得している:

Optimistic concurrency check failed. The row was modified outside of this cursor. 

私はそれをGoogleで検索しましたが、されていません問題に関する助けを見つけることができます。

この例外を防止するにはどうすればよいですか?あるいは、私がやりたいことをプログラムが行っているので、無視することはできますか?

+0

使用中のトランザクション分離レベルを教えてください。 – ordnungswidrig

+0

...また、あなたが更新する正確なクエリと正確な列は何ですか? – vladr

答えて

2

レコードは、データベースから(カーソルを介して)取得された瞬間から、それを元に戻そうとした瞬間までに変更されています。 number列が安全にいくつかの他のプロセスとは独立して、レコードまたはの残りの部分とは独立して更新することができた場合は、すでにいくつかの他の値にnumber列を設定した、あなたは何をする誘惑することができます

con.execute("update table set number = 20 where id=" & rs("id")) 

しかし、 競合状態が継続する、変更が別のプロセスによって上書きされることがあります。

最善の戦略は、にあるが再評価(はその後、失敗したレコードの上に第2のパスを行う、(メモリ内の)可能性のキューに失敗したレコードを押して、(レコードが更新されなかった)例外を無視しますqueryの条件と必要に応じて更新します。number <> 20queryの条件の1つとして追加します(これ以上のレコードがなくなるまで繰り返します)。最終的にすべてのレコードが更新されます。あなたが更新される行を正確に知っていると仮定すると、

+0

実際には、例外が発生してもレコードが更新されます –

+0

あなたの側で最適なロック例外をトリガーしている「他の誰か」が実際にあなたが見ている更新を実行している可能性はありますか? :) – vladr

+0

いいえ、更新は1か所でしか起こらず、私のプロセスはデータベースにアクセスする唯一のものです –

0

、私はあなたのAUTOCOMMIT

  • SETを行うだろうとOFF
  • テーブルFROM SERIALIZABLE
  • SELECT ROW1、ROW1へ
  • SET分離レベルWHERE UPDATE
  • FOR somecondition
  • UPDATE行
  • はCOMMIT

これは悲観的なロックによって実現されます(行のロックがDBでサポートされていると仮定すると、動作します)

関連する問題