30.10. 楽観的ロッキング

JBoss には、エンティティ bean の 楽観ロッキングに対するサポートがあります。楽観ロッキングによって、同じエンティティ bean の複数のインスタンスを同時にアクティブにすることができます。楽観ロッキングポリシー選択に基づいて一貫性を強化します。楽観ロッキングポリシー選択では、修正されたデータのデータベースへのコミット時間の書き込みに使用するフィールドセットを定義します。楽観ローディングの一貫性チェックでは、選択されたフィールドセットの値が、現行のトランザクションを開始した時点で存在していたデータベース内の値と同じであるということを表明します。これは、値のアサーションを含むselect for UPDATE WHERE ... ステートメントを使用して行われます。
楽観ロッキングポリシー選択は、jbosscmp-jdbc.xml 記述子の optimistic-locking 要素を使用して指定します。optimistic-locking 要素のコンテンツモデルを次に示し、その後に各要素の説明をします。
jbosscmp-jdbc optimistic-locking 要素コンテンツモデル

図30.14 jbosscmp-jdbc optimistic-locking 要素コンテンツモデル

  • group-name: この要素は、load-group のフィールドに基づく楽観ロッキングであることを指定します。この要素のこの値は、エンティティの load-group-nameのいずれかと一致していなければなりません。このグループ内のフィールドが楽観ロッキングに使用されます。
  • modified-strategy: この要素は、変更フィールドをベースにした楽観ロッキングであることを指定します。このストラテジーは、トランザクション中に修正されたフィールドが楽観ロッキングに使用されることを意味します。
  • read-strategy:この要素は、読み込まれたフィールドに基づく楽観ロッキングであることを指定します。このストラテジーは、トランザクション内の読み込み/変更されたフィールドが楽観ロッキングに使用されることを意味します。
  • version-column: この要素は、バージョンカラムストラテジーに基づく楽観ロッキングであることを指定します。この要素を指定すると、楽観ロッキング用にエンティティ bean に java.lang.Long タイプの追加のバージョンフィールドが追加されます。エンティティの更新ごとに、このフィールドの値が増えます。field-name 要素は、CMP フィールドの名前の指定を可能にするものであるのに対し、column-name 要素は、対応するテーブルのカラム指定ができるようになります。
  • timestamp-column: この要素は、タイムスタンプのカラムストラテジーに基づく楽観ロッキングであることを指定します。この要素を指定すると、楽観ロッキング用にエンティティ bean に java.util.Date タイプのバージョンフィールドが別途追加されます。エンティティの更新ごとに、このフィールドの値を現在時刻に設定します。field-name 要素は、CMP フィールドの名前の指定を可能にするものであるのに対し、column-name 要素は、対応するテーブルのカラム指定ができるようになります。
  • key-generator-factory:この要素は、キー生成に基づく楽観ロッキングであることを指定します。この要素の値は、org.jboss.ejb.plugins.keygenerator.KeyGeneratorFactory実装の JNDI 名です。この要素を指定すると、楽観ロッキング用にエンティティ bean にバージョンフィールドが別途追加されます。フィールドのタイプは field-type 要素で指定しなければなりません。エンティティの更新ごとに、キージェネレーターから新しい値を取得することでキーフィールドを更新します。field-name 要素は、CMP フィールドの名前の指定を可能にするものであるのに対し、column-name 要素は、対応するテーブルのカラム指定を可能にします。
すべての楽観ロッキングストラテジーを記した jbosscmp-jdbc.xml 記述子のサンプルを次に示します。
<!DOCTYPE jbosscmp-jdbc PUBLIC 
    "-//JBoss//DTD JBOSSCMP-JDBC 3.2//EN"
    "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_2.dtd">
<jbosscmp-jdbc>
    <defaults>
        <datasource>java:/DefaultDS</datasource>
        <datasource-mapping>Hypersonic SQL</datasource-mapping>
    </defaults>
    <enterprise-beans>
        <entity>
            <ejb-name>EntityGroupLocking</ejb-name>
            <create-table>true</create-table>
            <remove-table>true</remove-table>
            <table-name>entitygrouplocking</table-name>
            <cmp-field>
                <field-name>dateField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>integerField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>stringField</field-name>
            </cmp-field>
            <load-groups>
                <load-group>
                    <load-group-name>string</load-group-name>
                    <field-name>stringField</field-name>
                </load-group>
                <load-group>
                    <load-group-name>all</load-group-name>
                    <field-name>stringField</field-name>
                    <field-name>dateField</field-name>
                </load-group>
            </load-groups>
            <optimistic-locking>
                <group-name>string</group-name>
            </optimistic-locking>
        </entity>
        <entity>
            <ejb-name>EntityModifiedLocking</ejb-name>
            <create-table>true</create-table>
            <remove-table>true</remove-table>
            <table-name>entitymodifiedlocking</table-name>
            <cmp-field>
                <field-name>dateField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>integerField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>stringField</field-name>
            </cmp-field>
            <optimistic-locking>
                <modified-strategy/>
            </optimistic-locking>
        </entity>
        <entity>
            <ejb-name>EntityReadLocking</ejb-name>
            <create-table>true</create-table>
            <remove-table>true</remove-table>
            <table-name>entityreadlocking</table-name>
            <cmp-field>
                <field-name>dateField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>integerField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>stringField</field-name>
            </cmp-field>
            <optimistic-locking>
                <read-strategy/>
            </optimistic-locking>
        </entity>
        <entity>
            <ejb-name>EntityVersionLocking</ejb-name>
            <create-table>true</create-table>
            <remove-table>true</remove-table>
            <table-name>entityversionlocking</table-name>
            <cmp-field>
                <field-name>dateField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>integerField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>stringField</field-name>
            </cmp-field>
            <optimistic-locking>
                <version-column/>
                <field-name>versionField</field-name>
                <column-name>ol_version</column-name>
                <jdbc-type>INTEGER</jdbc-type>
                <sql-type>INTEGER(5)</sql-type>
            </optimistic-locking>
        </entity>
        <entity>
            <ejb-name>EntityTimestampLocking</ejb-name>
            <create-table>true</create-table>
            <remove-table>true</remove-table>
            <table-name>entitytimestamplocking</table-name>
            <cmp-field>
                <field-name>dateField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>integerField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>stringField</field-name>
            </cmp-field>
            <optimistic-locking>
                <timestamp-column/>
                <field-name>versionField</field-name>
                <column-name>ol_timestamp</column-name>
                <jdbc-type>TIMESTAMP</jdbc-type>
                <sql-type>DATETIME</sql-type>
            </optimistic-locking>
        </entity>
        <entity>
            <ejb-name>EntityKeyGeneratorLocking</ejb-name>
            <create-table>true</create-table>
            <remove-table>true</remove-table>
            <table-name>entitykeygenlocking</table-name>
            <cmp-field>
                <field-name>dateField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>integerField</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>stringField</field-name>
            </cmp-field>
            <optimistic-locking>
                <key-generator-factory>UUIDKeyGeneratorFactory</key-generator-factory>
                <field-type>java.lang.String</field-type>
                <field-name>uuidField</field-name>
                <column-name>ol_uuid</column-name>
                <jdbc-type>VARCHAR</jdbc-type>
                <sql-type>VARCHAR(32)</sql-type>
            </optimistic-locking>
        </entity>
    </enterprise-beans>
</jbosscmp-jdbc>