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