6.10.1 楽観的ロックの処理

楽観的ロックを使用すると,Cosminexus JPAプロバイダはデータベースのデータがほかのアプリケーションから更新されていないかをユーザに代わってチェックします。データベースのデータが更新されていると,Cosminexus JPAプロバイダは例外を発生させて,ユーザにデータが更新されていることを通知します。また,トランザクションをロールバックにマークします。

<この項の構成>
(1) データ更新の有無のチェック方法
(2) 永続化フィールドおよびリレーションシップのバージョンチェック
(3) flush操作またはトランザクションの決着時のバージョンチェック

(1) データ更新の有無のチェック方法

データが更新されているかどうかは,データベースのテーブル上に用意したバージョン列の更新の有無によってチェックします。データベース上のデータが更新されると,バージョン列のバージョン番号が更新されます。これによって,ほかのアプリケーションなどからデータベースが更新されたことがわかります。データベースを更新するときのバージョン列の状態と動作について次の表に示します。

表6-16 データベースを更新するときのバージョン列の状態と動作

テーブルのバージョン列の状態動作
バージョン列の値が更新されていない場合Cosminexus JPAプロバイダは,エンティティの情報をデータベースに反映します。このとき,データベースのバージョン列の値を更新します。
バージョン列の値が更新されている場合ほかのアプリケーションなどからデータベースのデータが更新されていることを表します。このため,Cosminexus JPAプロバイダはOptimisticLockExceptionを発生させて,トランザクションをロールバックにマークします。

このように,バージョン列の状態によって,エンティティを読み込んだ状態からデータベースを更新するまでに,ほかのトランザクションがデータを更新していないことを保証できます。

(2) 永続化フィールドおよびリレーションシップのバージョンチェック

楽観的ロックを使用するには,エンティティの永続化フィールドおよびリレーションシップの両方をバージョンチェックの対象にします。バージョンチェックの対象とするには,エンティティにバージョン列に対応するVersionフィールド(プロパティ)を設定してください。Versionフィールドは@VersionまたはO/Rマッピングファイルの<version>タグを使用して設定します。

エンティティのバージョンチェックは次のどちらかのタイミングで実行されます。

バージョンチェックによってエンティティのバージョンが古いことが判明した場合,OptimisticLockExceptionが発生します。また,トランザクションはロールバックにマークされます。

(3) flush操作またはトランザクションの決着時のバージョンチェック

エンティティをflush操作またはトランザクションの決着時にバージョンチェックの対象にできます。バージョンチェックの対象とするには,EntityManagerのlockメソッドにエンティティを指定します。EntityManagerのlockメソッドを使用することで,トランザクションでのバージョンチェック対象にエンティティを追加したり,バージョン列の更新方針を変更したりできます。

Cosminexus JPAプロバイダでは,バージョン列の更新タイミング(lockメソッドのLockModeType)としてLockModeType.READおよびLockModeType.WRITEの二つをサポートしています。バージョン列の更新タイミングの指定内容にかかわらず,Cosminexus JPAプロバイダではトランザクションの決着時に次に示す二つの事象が起きないことを保証します。

LockModeTypeとしてLockModeType.WRITEを指定すると,エンティティの状態変更がない場合でもバージョン列は強制的に更新されます。バージョン列の更新はflushまたはトランザクションのコミットが呼び出されたタイミングで実行されます。なお,バージョン列の更新前にエンティティが削除された場合,バージョン列の更新は省略されることもあります。