Hibernate開発者用ドキュメント-章V.ロック

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。 タイムスタンプ


タイムスタンプは、バージョン番号よりも信頼性の低い楽観的ロックの方法であり、アプリケーションが他の目的で使用することもできます。 DateCalendarなどのプロパティで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がキャプチャできるさまざまなレベルのロックを定義します。


上記の明示的なユーザー要求は、次のいずれかの結果として発生します。

UPGRADEまたはUPGRADE_NOWAITオプションを指定してSession.load()を呼び出し、要求されたオブジェクトがセッションによってまだロードされていない場合、オブジェクトはSELECT ... FOR UPDATEを使用してロードされます。 既にロードされているオブジェクトに対してload()を呼び出した場合、要求したロックほど厳密ではありませんが、Hibernateはそのオブジェクトに対してlock()を呼び出します。
Session.lock()は、READ、UPGRADE、またはUPGRADE_NOWAITモードでバージョン番号をチェックします。 UPGRADEまたはUPGRADE_NOWAITの場合、構文はSELECT ... FOR UPDATEになります。
要求されたロックモードがデータベースでサポートされていない場合、Hibernateは例外をスローする代わりに適切な代替モードを使用します。 これにより、アプリケーションの移植性が確保されます。

Source: https://habr.com/ru/post/J268903/


All Articles