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
もしくは、 UPGRADE
、 UPGRADE_NOWAIT
だった場合、 Session.lock()
は、バージョン番号のチェックを実施します。 UPGRADE
もしくは UPGRADE_NOWAIT
の場合、 SELECT ... FOR UPDATE
が使われます。
データベースが要求されたロックモードをサポートしていない場合、Hibernate は例外を投げる代わりに、適切な代わりのモードを使います。これは、アプリケーションがポータブルであることを保証します。