14

サードパーティのデータソースからのエンティティを独自のスキーマに同期するアプリケーションを作成しており、その間に変換/マッピングのステップがあります。Hibernate を使用して、独自のスキーマでエンティティを表現および永続化しています。私が直面している問題は、テーブルの 1 つに一意の複数列キーがあることです。私が見たい動作は upsert に似ています: Hibernate がエンティティを永続化し、一意の制約違反を検出すると、代わりに更新を行います。INSERT ... ON DUPLICATE KEY UPDATE 構文を提供する MySQL を使用していますが、Hibernate でそれを使用できるかどうか、またはどのように使用できるかわかりません。

いつでも挿入を試すことができ、例外をキャッチした場合は更新を行うことができると思いますが、それはハックで最適ではないようです。これを行うためのクリーンな方法に関するヒントはありますか?

4

2 に答える 2

10

INSERT ... ON DUPLICATE KEY UPDATE 構文を提供する MySQL を使用していますが、Hibernate でそれを使用できるかどうか、またはどのように使用できるかわかりません。

このエンティティに対して Hibernate が使用するステートメントをオーバーライドすることで、誰かがそれを行ったようです。sql-insert移植性がなくても構わない (そしておそらくストアド プロシージャを使用している) 場合は、ご覧ください。

いつでも挿入を試すことができ、例外をキャッチした場合は更新を行うことができると思いますが、それはハックで最適ではないようです。これを行うためのクリーンな方法に関するヒントはありますか?

別のオプションは次のとおりです。

  1. 一意のキーで選択を実行します
  2. 記録を見つけたら更新する
  3. レコードが見つからない場合は作成します

ただし、プロセス中にテーブル全体をロックしない限り、マルチスレッドおよび分散環境で何らかの競合状態に直面する可能性があり、ステップ 3 が失敗する可能性があります。2 つの同時スレッドを想像してください。

スレッド 1:

  • トランスを開始
  • キーの選択を実行します
  • レコードが見つかりません
  • 記録を作成する
  • 専念

スレッド 2:

  • トランスを開始
  • 同じキーで選択を実行します
  • レコードが見つかりません
  • 記録を作成する
  • commit ( FAIL!スレッド 1 の方が高速で、同じ一意のキーを持つレコードが存在するため)

したがって、何らかの再試行メカニズムを実装する必要があります (テーブル全体をロックすることは、IMO の適切なオプションではありません)。

于 2010-09-09T02:18:47.463 に答える
2

競合状態は「select ... for update」で回避できます

于 2012-07-28T22:55:40.183 に答える