MB blog

ちょっぴりテクニカルな話題のメモです。

JPA2.0のLockModeTypeについて


スポンサードリンク

JPA2.0における変更点

Java EE 6仕様の一部であるJPA2.0。
JPA1.0からの変更点のひとつに、エンティティ更新時のリソースロック機能として悲観ロックをサポートするようになった、というものがあります。EntityManager # find や lock といったメソッドの引数に指定できるデータベースのロックタイプ(javax.persistence.LockModeType)が、1.0までは

  • READ
  • WRITE

の2種類だったのが、

  • OPTIMISTIC
  • OPTIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_READ
  • PESSIMISTIC_WRITE
  • PESSIMISTIC_FORCE_INCREMENT

の5種類が追加されたようです。

また、Query # setLockMode というメソッドも新たに追加され、ユーザが定義したJPQLクエリ時代に、ロックタイプ属性を持たせられるようになっています。さて、新たに追加された5種類のLockModeTypeについて、Javadocを見ただけでは動きが分からなかったので、調べてみました。

楽観ロック

既存のREADとWRITEに対応するもののようです。READ, WRITEは今後、deprecatedになっていくのでしょうか?バージョン番号/最終更新時間による更新チェックをかけるので、バージョン更新に対応したエンティティオブジェクトにのみ対応している、という点も同様です。
ここでいう"バージョン更新に対応したエンティティオブジェクト"とは、以下の条件を満たすもののことです。

  • 対象となるテーブルに、バージョン番号 or 最終更新時間をあらわすカラムがある
  • 上記カラムに対応するフィールドを、エンティティBeanが持っている
  • 上記フィールドのセッターに @Version アノテーションが付与されている

JPA2.0で指定できる楽観ロックは、以下2タイプです。

OPTIMISTIC
  • エンティティ更新のコミット時にのみ、対象データをロックし、バージョン更新がかかる
OPTIMISTIC_FORCE_INCREMENT
  • エンティティ更新のコミット時だけでなく、ただエンティティを参照しただけでデータに変更を加えていない場合も、強制的にバージョン更新がかかる

悲観ロック

DBに長時間の排他ロックをかける悲観ロックは、1.0まではJPAの標準仕様ではサポートされていませんでした(各プロバイダの実装により、ヒント句を利用して悲観ロックをかける方法は存在しました)。なお悲観ロックにおいては、楽観ロックのように、バージョン更新に対応したエンティティオブジェクトを用意する必要はありませんが、もしバージョ更ン更新に対応したエンティティオブジェクトに悲観ロックをかけた場合は、楽観ロックと同じ方法でバージョンチェックおよび更新が行われます。JPA2.0で使用できる悲観ロックは、以下3タイプです。

PESSIMISTIC_READ
  • エンティティを取得した時点から、対象データにロックがかかる
  • コミット時にロック解放される
PESSIMISTIC_WRITE
  • エンティティを更新した時点から、対象データにロックがかかる
  • エンティティを取得・参照するだけだと、
  • 取得時から更新時までのあいだに他トランザクションに介入されたとき、更新失敗やデッドロック誘発のおそれがある
  • コミット時にロック解放される
PESSIMISTIC_FORCE_UPDATE
  • バージョン更新に対応したエンティティオブジェクトにしかかけられない
  • エンティティを取得した時点から、対象データにロックがかかる
  • エンティティを参照しただけで変更を加えていない場合も、強制的にバージョン更新がかかる
  • コミット時にロック解放される

〜参考〜
JSR-000317 JavaTM Persistence 2.0(Final Release)
Locking and Concurrency in Java Persistence 2.0