1

主キーとして user_id を持つマップされた User オブジェクトと、一意の制約を持つメール列があるとします。ユーザー オブジェクトが存在しない場合にのみ、ユーザー オブジェクトをユーザー テーブルに保存するプログラムが必要です。

挿入関数で次のことができます。

  1. 取引開始
  2. 指定されたメールを持つユーザーのクエリ
  3. 存在しない場合は、新しいユーザーを作成し、セッションを使用して保存します
  4. 失敗した場合はコミットまたはロールバック

2 つの問題があります。

  1. 2 つのクエリを実行するのはコストがかかります。プレーン SQL を使用していた場合は、「INSERT IGNORE」構文を使用する可能性がありますが、私の場合は休止状態の保存メソッドを使用し、最後に User オブジェクトを保持したいと考えています。それに対する解決策はありますか?
  2. 同時実行。アプリケーションの 2 つのインスタンスが同時に実行される可能性はありますか? どちらも同じ「mail」パラメータで「addUser」関数を使用します。1 つ目はフェーズ 2 を通過し、そのメールを持つユーザーを見つけられません。最初のインスタンスがまだユーザーを保存してコミットしていないため、2 番目のインスタンスもユーザーを見つけることなくフェーズ 2 を通過します。次に、最初のインスタンスがユーザーを保存してコミットし、その後、2 番目のインスタンスがユーザーを保存してコミットします。このユーザーには、最初のインスタンスのメールと同じメールが含まれます。もちろん、制約のために失敗します。何か不足していますか?

私が正しい場合、どうすればよいですか:

  1. それが起こらないことを願っています。
  2. トランザクションの開始時に、ユーザー テーブルを読み取りおよび書き込み用にロックします。
  3. 関数に try...except を追加すると、一意の制約例外が除外されます。例外がスローされた場合は、メールに従ってデータベースからユーザーを選択するだけです。
  4. 他の解決策...
4

3 に答える 3

0

今のところ、私ができるユニークな方法はうまくいきます:

<sql-insert check="none" callable="true">
            {call saveOrUpdate (?, ?, ?, ?, ?)}
 </sql-insert>

http://forum.springsource.org/showthread.php?65265-Hibernate-insert-problem

その他のオプションは機能しません:

@SQLInsert Hibernate アノテーションを使用して「存在しない場所に挿入」できるかもしれません

次のオプションは編集インスタンス専用です。

他のオプションは、「バージョン列を使用した楽観的ロック」を使用し、同時実行例外が発生した場合に例外を処理することです。

リンク: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html#transactions-optimistic

于 2011-09-22T10:11:26.693 に答える
0

一意の制約違反を適切に処理することに専念する必要があります。

これを行うには、スローされる ConstraintViolationException をキャッチします。よりきめ細かくしたい場合、おそらく複数の制約違反が発生する可能性がある場合は、次のようにすることができます。

...
} catch (ConstraintViolationException e) {
    if (e.getConstraintName() != null && e.getConstraintName().toLowerCase().equals("the_name_of_your_contraint")) {
        // do something, like add an error to be displayed on the UI
    }
}
于 2009-02-26T01:11:28.900 に答える