オプティミスティック・ロック・ストラテジーを使用しているときは、OptimisticCallback プラグインによってキャッシュ・オブジェクトのバージョン管理および比較操作をカスタマイズすることができます。
com.ibm.websphere.objectgrid.plugins.OptimisticCallback インターフェースを実装するプラグ可能オプティミスティック・コールバック・オブジェクトを用意できます。エンティティー・マップの場合、ハイパフォーマンス OptimisticCallback プラグインが自動的に構成されます。
OptimisticCallback インターフェースを使用して、マップの値としてオプティミスティック比較演算を提供します。オプティミスティック・ロック・ストラテジーを使用するときは、OptimisticCallback プラグインが必要です。 この製品 はデフォルトの OptimisticCallback 実装を提供しています。ただし、通常、アプリケーションは独自の OptimisticCallback インターフェースの実装をプラグインする必要があります。
public interface Employee
{
// Sequential sequence number used for optimistic versioning.
public long getSequenceNumber();
public void setSequenceNumber(long newSequenceNumber);
// Other get/set methods for other fields of Employee object.
}
この例では、ローダーは、getSequenceNumber メソッドを使用して、Employee 値オブジェクトの現行バージョン情報を取得できることを認識しています。 ローダーは、戻り値を増分して、新規 Employee 値で永続ストレージを更新する前に、新規バージョン番号を生成します。 Java Database Connectivity (JDBC) ローダーの場合、過剰 SQL UPDATE ステートメントの WHERE 文節内の現行シーケンス番号が使用され、新規生成シーケンス番号を使用して、シーケンス番号列が新規シーケンス番号の値に設定されます。 このほかにも、オプティミスティック・バージョン管理に使用できる非表示の列を自動的に 更新するなんらかのバックエンド提供の関数をローダーが利用する可能性があります。
状況によっては、ストアード・プロシージャーまたはトリガーを使用して、バージョン情報が入っている列を保守できるようにすることもあります。 ローダーが、オプティミスティック・バージョン情報を保守するためにこれらの技法のいずれかを使用している場合は、アプリケーションが OptimisticCallback 実装を提供する必要はありません。デフォルトの OptimisticCallback 実装は、ローダーが OptimisticCallback オブジェクトからの支援なしにオプティミスティック・バージョン管理を処理できるため、このシナリオでは便利です。
エンティティーは、タプル・オブジェクトを使用して、ObjectGrid に保管されます。 デフォルトの OptimisticCallback 実装の振る舞いは、非エンティティー・マップに対する振る舞いと似ています。 ただし、エンティティー内のバージョン・フィールドは、エンティティー記述子 XML ファイルの @Version アノテーションまたはバージョン属性を使用して識別されます。
バージョン属性の型は、int、Integer、short、Short、long、Long、java.sql.Timestamp のいずれかになります。エンティティーにはバージョン属性を 1 つだけ定義することができます。 バージョン属性は構成時にのみ設定するようにしてください。 エンティティーが永続化されると、バージョン属性の値は変更してはなりません。
バージョン属性が構成されず、オプティミスティック・ロック・ストラテジーが使用される場合、タプルの全体の状態を使用して、タプル全体が暗黙的にバージョン設定されますが、これははるかに高コストになります。
@Entity
public class Employee
{
private long sequence;
// Sequential sequence number used for optimistic versioning.
@Version
public long getSequenceNumber() {
return sequence;
}
public void setSequenceNumber(long newSequenceNumber) {
this.sequence = newSequenceNumber;
}
// Other get/set methods for other fields of Employee object.
}
OptimisticCallback プラグインは、OptimisticCallback インターフェースを実装し、共通 ObjectGrid プラグイン規則に準拠する必要があります。 詳しくは、OptimisticCallback インターフェースを参照してください。
次のリストには、OptimisticCallback インターフェース内の各メソッドについての説明または考慮事項があります。
この特殊値は、OptimisticCallback 実装がバージョン検査を必要としない場合に、getVersionedObjectForValue メソッドによって戻されます。 com.ibm.websphere.objectgrid.plugins.builtins.NoVersioningOptimisticCallback クラスの組み込みプラグイン実装では、このプラグイン実装を指定するとバージョン管理が使用不可になるため、この値が使用されます。
getVersionedObjectForValue メソッドは、バージョン管理のために使用できる値のコピーまたは値の属性を戻すことがあります。 このメソッドは、オブジェクトがトランザクションに関連付けられるたびに呼び出されます。 ローダーがバックアップ・マップ内にプラグインしていない場合、 バックアップ・マップは、コミット時刻にこの値を使用してオプティミスティック・バージョン管理比較を行います。 オプティミスティック・バージョン管理比較は、このトランザクションがこのトランザクションによって変更されたマップ・エントリーに最初にアクセスした後でバージョンが変更されていないことを確認するために、バックアップ・マップによって使用されます。 別のトランザクションが既にこのマップ・エントリーのバージョンを変更している場合、バージョン比較は失敗し、バックアップ・マップは OptimisticCollisionException 例外を表示して、トランザクションを強制的にロールバックします。 ローダーがプラグインされている場合、 バックアップ・マップはオプティミスティック・バージョン管理情報を使用しません。 代わりに、ローダーは、オプティミスティック・バージョン管理比較を行い、 必要に応じてバージョン管理情報を更新する責任があります。 ローダーは通常、ローダーの batchUpdate メソッドに渡される LogElement から、初期バージョン管理オブジェクトを取得します。このオブジェクトは、フラッシュ操作が発生するか、トランザクションがコミットされたときに呼び出されます。
public Object getVersionedObjectForValue(Object value)
{
if (value == null)
{
return null;
}
else
{
Employee emp = (Employee) value;
return new Long( emp.getSequenceNumber() );
}
}
前の例に示すように、sequenceNumber 属性は、ローダーが予期するように、java.lang.Long オブジェクト内に戻されます。これは、ローダーの作成者と同一人物が EmployeeOptimisticCallbackImpl を作成したか、 EmployeeOptimisticCallbackImpl を実装した人物と協力して作業を行ったか (例えば、getVersionedObjectForValue メソッドによって戻された値に合意した) のいずれかであることを示しています。 デフォルトの OptimisticCallback プラグインは、特殊値 NULL_OPTIMISTIC_VERSION をバージョン・オブジェクトとして戻します。
public void updateVersionedObjectForValue(Object value)
{
if ( value != null )
{
Employee emp = (Employee) value;
long next = emp.getSequenceNumber() + 1;
emp.updateSequenceNumber( next );
}
}
前の例で示すように、sequenceNumber 属性は、次に getVersionedObjectForValue メソッドが呼び出されたときに、戻される java.lang.Long 値が長整数値を持つように、1 ずつ増分されます。この長整数値は、元のシーケンス番号の値に 1 を加えたもの (例えば、この従業員インスタンスの次のバージョン値) です。 この例は、ローダーを作成者が EmployeeOptimisticCallbackImpl の作成者と同一人物であるか、 EmployeeOptimisticCallbackImpl を実装した人物と協力して作業を行ったかのいずれかであることを示しています。
このメソッドは、指定されたストリームにバージョン値を書き込みます。 実装によっては、バージョン値を使用して、オプティミスティック更新の衝突を識別することができます。 一部の実装では、バージョン値は元の値のコピーです。 それ以外の実装では、値のバージョンを示すシーケンス番号またはその他のいくつかのオブジェクトがあります。 実際の実装が不明であるため、このメソッドは適切なシリアライゼーションを実行するために提供されます。 デフォルト実装は writeObject メソッドを呼び出します。
このメソッドは、バージョン値のシリアライズ・バージョンを取り、実際のバージョン値オブジェクトを戻します。 実装によっては、バージョン値を使用して、オプティミスティック更新の衝突を識別することができます。 一部の実装では、バージョン値は元の値のコピーです。 それ以外の実装では、 値のバージョンを示すシーケンス番号またはその他のいくつかのオブジェクトがあります。 実際の実装が不明であるため、このメソッドは適切なデシリアライゼーションを行うために提供されます。 デフォルト実装は readObject メソッドを呼び出します。
アプリケーション提供の OptimisticCallback オブジェクトを BackingMap 構成に追加する場合、XML 構成とプログラマチック構成の 2 つの方法があります。
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.BackingMap;
ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();
ObjectGrid og = ogManager.createObjectGrid( "grid1" );
BackingMap bm = dg.defineMap("employees");
EmployeeOptimisticCallbackImpl cb = new EmployeeOptimisticCallbackImpl();
bm.setOptimisticCallback( cb );
<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
xmlns="http://ibm.com/ws/objectgrid/config">
<objectGrids>
<objectGrid name="grid1">
<backingMap name="employees" pluginCollectionRef="employees" lockStrategy="OPTIMISTIC" />
</objectGrid>
</objectGrids>
<backingMapPluginCollections>
<backingMapPluginCollection id="employees">
<bean id="OptimisticCallback" className="com.xyz.EmployeeOptimisticCallbackImpl" />
</backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>