Hibernateの公式ドキュメントの第5章の翻訳を紹介します。記事の翻訳は、バージョンHibernate 4.2.19.Finalに関連しています前章 -Hibernate開発者ドキュメント-章IV。 バッチ処理次の章 -Hibernate開発者ドキュメント-第VI章。 キャッシング内容5.1。 明るいロック5.1.1専用バージョン番号5.1.2。 タイムスタンプ5.2。 悲観的ロックロックは、読み取り時と使用時との間のリレーショナルデータベースのデータ変更を防止する手段です。
ブロック戦略は楽観的または悲観的のいずれかです。
ブロッキング戦略明るい楽観的ロックは、多くのトランザクションが相互に影響を与えることなく完了することができるため、影響するリソースをブロックすることなく実行できることを示唆しています。 コミットする前に、各トランザクションは、他のトランザクションがそのデータを変更していないことを確認します。 チェックにより競合する変更が明らかになった場合、コミット状態のトランザクションはロールバックされます。
悲観的悲観的な戦略は、並列トランザクションが互いに競合し、読み取り後にリソースをロックし、アプリケーションがデータの使用を終了した後にのみリソースを削除する必要があることを意味します。
Hibernateは、アプリケーションに両方のロック戦略を実装するメカニズムを提供します。
5.1。 明るいロック
アプリケーションが、複数のデータベーストランザクションにまたがる長時間のトランザクションまたはダイアログを使用する場合、バージョン付きデータを保存できます。 したがって、同じエンティティが2つのダイアログによって変更された場合、変更をコミットする最後のダイアログには競合が通知され、別のダイアログの結果は上書きされません。 このアプローチにより、ある程度の分離が保証されますが、拡張性が高く、
Read-Often Write-Sometimesの状況で
も非常にうまく機能します。
Hibernateは、バージョン情報を保存するための2つの異なるメカニズムを提供します-専用バージョン番号または
タイムスタンプ 。
バージョン番号タイムスタンプ重要ですデタッチされたオブジェクトのバージョンまたはタイムスタンププロパティをnullにすることはできません。 Hibernateは、指定した他の未保存値 *戦略に関係なく、 nullに等しいバージョン(またはタイムスタンプ)を持つインスタンスをtransientとして認識します。 nullバージョンのプロパティまたはタイムスタンプを宣言すると、Hibernateでの推移的な再接続の問題を簡単に回避できます。これは、 割り当てられた識別子または複合キーを使用する場合に特に便利です。
* unsaved-value -ID、バージョン、またはタイムスタンプを使用して投影されたプロパティの値に応じて、データベースとの同期のためのUPDATEまたはINSERT操作を定義するための戦略(約transl。)
5.1.1。 専用バージョン番号
楽観的ロックのバージョン番号メカニズムは、バージョン注釈によって提供されます。
例5.1。 アブストラクト版@Entity public class Flight implements Serializable { ... @Version @Column(name="OPTLOCK") public Integer getVersion() { ... } }
ここで、バージョンプロパティはOPTLOCK列にマップされ、
エンティティマネージャーはそれを使用して競合する更新を識別し、
最終コミット勝利戦略によって上書きされる更新の損失を防ぎます。
適切な
UserVersionTypeを定義および実装する場合、バージョン列はどのタイプでも
かまいません 。
アプリケーションは、Hibernateによって付加されたバージョン番号を変更できません。 バージョン番号を人為的に増やすには、Hibernate Entity Managerドキュメントの
LockModeType.OPTIMISTIC_FORCE_INCREMENTまたは
LockModeType.PESSIMISTIC_FORCE_INCREMENTプロパティの説明を参照してください。 バージョン番号がトリガーなどのデータベースによって生成される場合、アノテーション
org.hibernate.annotations.Generated(GenerationTime.ALWAYS)を使用します。
例5.2。 hbm.xmlでバージョンプロパティを宣言する <version column="version_column" name="propertyName" type="typename" access="field|property|ClassName" unsaved-value="null|negative|undefined" generated="never|always" insert="true|false" node="element-name|@attribute-name|element/@attribute|." />
名 | 説明 |
---|
コラム | バージョン番号が配置されている列の名前。 オプションで、デフォルトはプロパティ名と同じです。 |
お名前 | 永続クラスのプロパティの名前。 |
タイプ | バージョン番号のタイプ。 オプションで、デフォルトの整数。 |
アクセス | プロパティ値にアクセスするためのHibernate戦略。 オプション、デフォルトのプロパティ |
未保存値 | インスタンスが作成されたばかりであり、保存されていないことを示します。 分離されたエンティティからの抽出( detached )。 デフォルト値のundefinedは、識別子プロパティを使用しないことを示します。 必要に応じて。 |
生成された | データベースによってバージョンプロパティを生成する必要があることを示します。 オプションで、デフォルトでは決してありません。 |
挿入する | SQL-insertステートメントにバージョン列を含めるかどうか。 デフォルトはtrueですが、データベースの列がデフォルト値0で定義されている場合はfalseに設定できます |
5.1.2。 タイムスタンプ
タイムスタンプは、バージョン番号よりも信頼性の低い楽観的ロックの方法であり、アプリケーションが他の目的で使用することもできます。
Dateや
Calendarなどのプロパティで
Version注釈を使用すると、タイムスタンプが自動的に使用されます。
例5.3 楽観的ロックにタイムスタンプを使用する @Entity public class Flight implements Serializable { ... @Version public Date getLastUpdate() { ... } }
Hibernateは、アノテーション値
org.hibernate.annotations.Sourceを読み取ることにより、データベースまたはJVMからタイムスタンプ値を取得できます。 値は
org.hibernate.annotations.SourceType.DBまたは
org.hibernate.annotations.SourceType.VMのいずれかです。 デフォルトの動作はデータベースを使用することであり、注釈を指定しない場合にも使用されます。
注釈
org.hibernate.annotations.Generated(GenerationTime.ALWAYS)を使用する場合、Hibernateの代わりにデータベースによってタイムスタンプを生成することもできます。
例5.4 hbm.xmlのタイムスタンプ要素 <timestamp column="timestamp_column" name="propertyName" access="field|property|ClassName" unsaved-value="null|undefined" source="vm|db" generated="never|always" node="element-name|@attribute-name|element/@attribute|." />
名 | 説明 |
---|
コラム | タイムスタンプが配置されている列の名前。 オプション、デフォルト プロパティ名と同じ。 |
お名前 | 永続プロパティのDate型またはTimestamp型のJavaBeansプロパティの名前。 |
アクセス | Hibernateがプロパティの値にアクセスするために使用する戦略。 オプションのデフォルトのプロパティ。 |
未保存値 | インスタンスが作成されたばかりであり、保存されていないことを示します。 ハイライト 切り離されたエンティティから(切り離された)。 デフォルト値、未定義は、示します 識別子プロパティは使用しないでください。 必要に応じて。
|
ソース | Hibernateがデータベースまたは現在のJVMからラベルを取得するかどうか。 Hibernateは増分を決定するために毎回データベースを照会する必要があるため、DBタグは余分なオーバーヘッドをもたらします。 ただし、dbタグは、 クラスター環境。 すべてのデータベース方言がデータベースからの現在のタイムスタンプの抽出をサポートしているわけではありません。 他のものは、精度が不足しているため、ロックに対して安全ではない場合があります。
|
生成された | データベースによってラベルが生成されるかどうか。 オプションで、デフォルトでは決してありません。 |
5.2。 悲観的ロック
LockModeクラスは、Hibernateがキャプチャできるさまざまなレベルのロックを定義します。
- LockMode.WRITE
Hibernateが行を更新または挿入すると自動的にキャプチャされます。 - LockMode.UPGRADE
この構文をサポートするデータベースでSELECT ... FOR UPDATEを使用した明示的なユーザー要求の後にキャプチャされます。 - LockMode.UPGRADE_NOWAIT
OracleのSELECT ... FOR UPDATE NOWAITを使用した明示的なユーザー要求後にキャプチャ - LockMode.READ
HibernateがRepeatable ReadまたはSerializableの分離レベルでデータを読み取るときに自動的にキャプチャされます。 明示的なユーザーリクエストによって再取得される場合があります。 - LockMode.NONE
ブロッキングの欠如。 すべてのオブジェクトは、トランザクションの終了時にこのロックモードに切り替わります。 セッション関連オブジェクト
update()またはsaveOrUpdateの呼び出しによっても、このモードで開始されます。
上記の明示的なユーザー要求は、次のいずれかの結果として発生します。
- Session.load()呼び出し、 LockModeを示す
- Session.lock()を呼び出します
- Query.setLockMode()を呼び出します
UPGRADEまたはUPGRADE_NOWAITオプションを指定して
Session.load()を呼び出し、要求されたオブジェクトがセッションによってまだロードされていない場合、オブジェクトはSELECT ... FOR UPDATEを使用してロードされます。 既にロードされているオブジェクトに対して
load()を呼び出した場合、要求したロックほど厳密ではありませんが、Hibernateはそのオブジェクトに対して
lock()を呼び出します。
Session.lock()は、READ、UPGRADE、またはUPGRADE_NOWAITモードでバージョン番号をチェックします。 UPGRADEまたはUPGRADE_NOWAITの場合、構文はSELECT ... FOR UPDATEになります。
要求されたロックモードがデータベースでサポートされていない場合、Hibernateは例外をスローする代わりに適切な代替モードを使用します。 これにより、アプリケーションの移植性が確保されます。