Red Hat Training

A Red Hat training course is available for Red Hat JBoss Web Server

12.4. 悲観的ロック

悲観的ロックは、ユーザーがロック戦略に悩むのに多くの時間を費やすためのものではありません。通常は、JDBC コネクションに分離レベルを指定し、単にデータベースにすべての処理をさせれば十分です。しかしながら、高度なユーザーは、排他的な悲観的ロックの獲得や、新しいトランザクションが開始される際のロックの再獲得をしたいと考えるかもしれません。
Hibernate はいつもデータベースのロックの仕組みを使います。メモリ内のオブジェクトを決してロックしません。
LockMode クラスは、Hibernate が獲得できる異なるロックレベルを定義します。以下の仕組みにより、ロックを獲得します。
  • LockMode.WRITE は、 Hibernate が行を更新もしくは挿入する際に自動的に得られます。
  • LockMode.UPGRADE は、データベースでサポートされている文法 SELECT ... FOR UPDATE を使いユーザーが明示的に要求することで得ることができます。
  • LockMode.UPGRADE_NOWAIT は、 Oracle で SELECT ... FOR UPDATE NOWAIT を使いユーザーが明示的に要求することで得ることができます。
  • LockMode.READ は、 Repeatable Read もしくは Serializable の分離レベルで、データを読んだ際に自動的に得られます。明示的なユーザー要求により、再取得されます。
  • LockMode.NONE は、ロックしないことを表します。 Transaction の終わりに、すべてのオブジェクトはこのロックモードに切り替わります。 update()saveOrUpdate() を呼び出すことによって、セッションに関連付けられたオブジェクトも、このロックモードで出発します。
「明示的なユーザー要求」とは、下記の方法の1つで言い表せます。
  • LockMode を指定した Session.load() の呼び出し。
  • Session.lock() の呼び出し。
  • Query.setLockMode() の呼び出し。
UPGRADE もしくは UPGRADE_NOWAIT が指定された Session.load() が呼び出され、かつ要求されたオブジェクトがセッションによってまだロードされていなかった場合は、 SELECT ... FOR UPDATE を使って、オブジェクトがロードされます。 load() で呼び出されたオブジェクトが、要求されているより制限が少ないロックですでにロードされていた場合は、 Hibernate はそのオブジェクトのために、 lock() を呼び出します。
指定されたロックモードが READ もしくは、 UPGRADEUPGRADE_NOWAIT だった場合、 Session.lock() は、バージョン番号のチェックを実施します。 UPGRADE もしくは UPGRADE_NOWAIT の場合、 SELECT ... FOR UPDATE が使われます。
データベースが要求されたロックモードをサポートしていない場合、Hibernate は例外を投げる代わりに、適切な代わりのモードを使います。これは、アプリケーションがポータブルであることを保証します。