11.3. 楽観的同時実行制御

高い並列性と高いスケーラビリティの両方を実現するアプローチは、バージョニングを使った楽観的同時実行制御のみです。更新の衝突を見つけ、更新が失われるのを防ぐために、バージョン番号もしくはタイムスタンプを使って、バージョンをチェックします。Hibernate は、楽観的同時実行を行うアプリケーションコードを書くためのアプローチを3つ提供します。ここでお話するユースケースは、長い会話といったコンテキストですが、バージョンチェックは1つのデータベーストランザクションの中で更新を失うことを防ぐ利点も持っています。

11.3.1. アプリケーションによるバージョンチェック

Hibernate の支援がほぼない状態で実装するケースにおいて、データベースとのやり取りは、それぞれ新しい Session の中で起こります。開発者は、すべての永続性インスタンスを操作する前に、データベースから再読み込みする責務があります。会話トランザクションの分離を確保するために、アプリケーション自身がバージョンチェックを行う必要があります。このアプローチは、データベースアクセスの中では、最も非効率で、エンティティ EJB と最も似ているアプローチです。
// foo is an instance loaded by a previous Session
session = factory.openSession();
Transaction t = session.beginTransaction();

int oldVersion = foo.getVersion();
session.load( foo, foo.getKey() ); // load the current state
if ( oldVersion != foo.getVersion() ) throw new StaleObjectStateException("Message", foo.getId()); 
foo.setProperty("bar");

t.commit();
session.close();
<version> を使って、 version プロパティをマッピングします。 Hibernate は、エンティティがダーティである場合、フラッシュし、その間に version プロパティを自動的にインクリメントします。
データの並列性が低い環境で運用しており、バージョンチェックが不要なら、このアプローチを使い、バージョンチェックをスキップすることができます。この場合は、長い会話には、最後にコミットしたものが勝つ がデフォルトの戦略でしょう。このアプローチは、アプリケーションのユーザーを混乱させるかもしれないことを心に留めて置いてください。それは、エラーメッセージや競合した変更をマージする機会がないまま、更新を失う可能性があるからです。
マニュアルによるバージョンチェックは、普通の状況であれば実行できますが、多くのアプリケーションにとって実用的ではありません。1つのインスタンスだけでなく、修正されたオブジェクトの完全なグラフをチェックしなければなりません。Hibernate は、設計パラダイムとして、拡張 Session か分離されたインスタンスを自動的にバージョンチェックします。