1

拡張セッション/自動バージョン管理を使用した標準的な楽観的同時実行制御シナリオで遊んでいます。最初のトランザクションでロードし、変更のためにユーザーに提示し、2番目のトランザクションで保存するエンティティがあり、両方のトランザクションが同じセッションを共有しています。エンティティが何らかの形で 2 番目のトランザクションの最後に変更された後、バージョンの不一致が検出された場合、並行トランザクションがその間にエンティティの次のバージョンを保存したことを意味する session.flush()がスローされる可能性があります。StaleObjectStateException

このようなエラーを最も簡単な方法で処理したいと思います。現在の変更を失うエンティティをリロードし、編集と保存を再度続行するだけです。最初にこれを試しました:

session.refresh(entity);

しかし、この更新されたエンティティを変更して保存しようとすると、StaleObjectStateException更新されてバージョン番号が一貫しているように見えても、同じ . refresh()はい、延長セッションでの使用はお勧めできないことは知っていますが、その理由はわかりません。この行動は、それが推奨されない理由に関連していますか?

次に、使用を避けるために次の方法を試しましたsession.refresh()

session.evict(entity);
entity = session.load(MyEntity.class, id);

しかし、それStaleObjectStateExceptionは実際には古くないエンティティを保存するときに発生します。

例外に対処できた唯一の方法は次のとおりです。

session.clear();
entity = session.load(MyEntity.class, id);

しかし、私の具体的なエンティティに関するものsession.clear()と同じではありませんか?session.evict()

再開するには、私の質問は次のとおりです。

  • が行われStaleObjectStateExceptionない限り、リロードされたエンティティでまだスローされるのはなぜですか?session.clear()
  • 同じセッションで既にロードされているエンティティをリロードする正しい方法は何ですか?なぜrefresh()悪いのですか? 会話を実装するこのアプローチには何か問題がありますか?

二次キャッシュなしで Hibernate 4.1.7.Final を使用しています。

私の質問が繰り返されている場合は申し訳ありませんが、深い説明を見つけることができません...

4

1 に答える 1

2

セッションで例外が発生すると、そのセッションインスタンスが壊れます。そのインスタンスはもう使用できず、破棄して新しいインスタンスを作成する必要があります。例外はリセットされません(論理的にはこれは発生しないはずですが、同じ例外が再び発生することがわかります)。これは、Hibernateセッションを使用するための一般的なルールです。この理由は、Hibernateが例外が表示される理由を常に認識しているわけではなく、セッションインスタンスの状態に一貫性がない可能性があるためです。

clear()の後でなぜ機能するのかわかりません。これは偶然かもしれません。新しいインスタンスを使用する方が賢明です。

StatelessSessionを使用する場合、この制限はありませんが、ステートレスセッションには他の欠点があります。たとえば、キャッシュがありません。

于 2012-11-27T07:37:08.133 に答える