11.3.2. 拡張セッションと自動バージョニング

1つの Session インスタンスとその永続性インスタンスは、 session-per-conversation として知られる、会話全体で使われます。Hibernate はフラッシュする際に、インスタンスのバージョンをチェックします。同時修正を検出すると、例外を投げます。この例外をキャッチして処理するかは開発者次第です。一般的な選択肢は、変更をマージするか無効でないデータでビジネス会話を再スタートする機会をユーザーに提供することです。
ユーザーの対話を待っているときは、Session を基礎となる JDBC コネクションから切断します。このアプローチは、データベースアクセスの中では、最も効率的です。アプリケーションは、バージョンチェックや分離されたインスタンスの再接続、あらゆるデータベーストランザクションの中でインスタンスを再読み込みを行う必要はありません。
// foo is an instance loaded earlier by the old session
Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start transaction

foo.setProperty("bar");

session.flush();    // Only for last transaction in conversation
t.commit();         // Also return JDBC connection
session.close();    // Only for last transaction in conversation
foo オブジェクトは、自分をロードした Session を把握しいます。古いセッション上で新しいデータベーストランザクションを開始することで、新しいコネクションを取得し、そのセッションが再開されます。データベーストランザクションをコミットすることで、セッションから JDBC コネクションを切断し、コネクションをプールに返します。再接続した後、更新していないデータのバージョンチェックを強制するために、他のトランザクションにより更新されているかもしれないオブジェクトに関して、 LockMode.READ をつけて Session.lock() を呼び出すことができます。更新して いる データをロックする必要はありません。通常、拡張 SessionFlushMode.NEVER をセットします。最後のデータベーストランザクションの周期でのみ、会話の中で変更されたすべてを実際に永続化させることができます。ゆえに、この最後のデータベーストランザクションのみが flush() オペレーションを含みます。そして、会話を終わらせるために、セッションも close() します。
ユーザーが考慮中に、格納することができないくらい Session が大きいのであれば、このパターンは問題があります(例えば、 HttpSession は可能な限り小さく保つべきです)。 Session は (強制的に) 1次キャッシュでもあり、ロードしたオブジェクトをすべて保持しするため、おそらく、リクエスト/レスポンスのサイクルが2〜3回のみであれば、この戦略が使えます。データの期限がすぐに切れるため、1つの会話のためだけに Session を使いましょう。

注記

Hibernate の以前のバージョンは、明示的な Session の切断と再接続が必要でした。トランザクションの開始と終了は同じ効果があるため、これらのメソッドは推奨されません。
切断した Session を永続化層の近くで保持すべきであることに注意してください。また、EJB ステートフルセッション Bean を使い、3層環境の中で Session を保持してください。HttpSession に格納するために、 Web 層への転送、別の層へのシリアライズは行わないでください。
拡張セッションパターン、もしくは、session-per-conversation は、自動的なカレントセッションコンテキスト管理を実施するより難しく、これについては、自身でCurrentSessionContext の実装を供給する必要があります。Hibernate Wiki にある例を参照してください。