1. ホーム
  2. java

[解決済み] JPA並行処理問題 "バッチリリース時にJDBC文が残っていた" について

2022-02-27 22:59:45

質問

あるエンティティの保存を最大再試行回数に達するまで何度も試みるwhileループで解決しようとした並行処理の問題があります。この問題を解決する他の方法があるかどうかについての話は避けたいと思います。それについてはStackoverflowの他の投稿を参照してください。) 長い話を簡単にすると、派生したカラムに一意制約があり、衝突を避けるために増分し続ける数値部分を含んでいます。ループの中で、私は。

  1. select max(some_value)
  2. 結果のインクリメント
  3. この新しい結果で新しいオブジェクトを保存しようとする
  4. 明示的にエンティティをフラッシュし、ユニークインデックスが原因で失敗した場合、DataAccessExceptionをキャッチします。

ループがステップ1に戻って選択しようとするとき、私は得ることを除いて、このすべてが動作しているように見える。

17:20:46,111 INFO  [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] (http-localhost/127.0.0.1:8080-3) HHH000010: On release of batch it still contained JDBC statements
17:20:46,111 INFO  [my.Class] (http-localhost/127.0.0.1:8080-3) MESSAGE="Failed to save to database. Will retry (retry count now at: 9) Exception: could not execute statement; SQL [n/a]; constraint [SCHEMA_NAME.UNIQUE_CONSTRAINT_NAME]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"

そして、新たなExceptionがキャッチされます。一意制約違反の原因となる最初のフラッシュで DataAccessException は、エンティティ・マネージャのバッチをクリアしません。この場合、どのように対処するのが適切でしょうか?私はJPAでSpringを使用しており、エンティティマネージャに直接アクセスすることはできません。必要であればインジェクトすることはできると思いますが、それはこの問題に対する苦痛の解決策です。

解決方法は?

一度何かをフラッシュし、それが失敗して例外がスローされると、トランザクションはロールバックとしてマークされます。つまり、例外をキャッチして処理を続行しても、結局はロールバックされてしまうということです。 実際、どんな例外が投げられたかは全く問題ではありません。Springのトランザクションマネージャはデフォルトで、すべての チェックされていない 例外が発生します。 この問題を解決するには noRollbackFor の上に @Transactional アノテーション (アノテーションドライバトランザクションを使用している場合)

編集 - この制約違反の場合、トランザクションはおそらくデータベースレベルでロールバックとしてマークされるため、これも役に立ちません。