拡張機能を使用する - AWS SDK for Java 2.x

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

拡張機能を使用する

DynamoDB 拡張クライアント API は、マッピング操作以外の機能を提供するプラグイン拡張機能をサポートしています。エクステンションには、beforeWrite()afterRead() の 2 つのフックメソッドがあります。beforeWrite() は書き込み操作を発生する前に変更し、afterRead() メソッドは読み取り操作が行われた後にその結果を変更します。一部のオペレーション (アイテムの更新など) は書き込みと読み取りの両方を実行するため、両方のフックメソッドが呼び出されます。

拡張機能は、拡張クライアントビルダーで指定された順序でロードされます。1 つのエクステンションが以前のエクステンションによって変換された値に作用する可能性があるため、ロード順序は重要な場合があります。

拡張クライアント API には、extensions パッケージに含まれる一連のプラグイン拡張が付属しています。デフォルトでは、拡張クライアントは VersionedRecordExtensionAtomicCounterExtension をロードします。Enhance クライアントビルダーでデフォルトの動作を上書きして、任意の拡張機能を読み込むことができます。デフォルトの拡張機能を使いたくない場合は、none を指定することもできます。

独自の拡張機能をロードしても、拡張クライアントはデフォルトの拡張機能をロードしません。いずれかのデフォルトの拡張機能と同じ動作をさせたい場合は、拡張機能のリストに明示的に追加する必要があります。

次の例では、verifyChecksumExtension という名前のカスタム拡張機能が VersionedRecordExtension の後にロードされます。通常、カスタム拡張機能はデフォルトで単独でロードされます。この例では、AtomicCounterExtension はロードされていません。

DynamoDbEnhancedClientExtension versionedRecordExtension = VersionedRecordExtension.builder().build(); DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(dynamoDbClient) .extensions(versionedRecordExtension, verifyChecksumExtension) .build();

VersionedRecordExtension

VersionedRecordExtension はデフォルトでロードされ、アイテムがデータベースに書き込まれるとアイテムのバージョン番号が増加して追跡されます。実際に保存されているアイテムのバージョン番号がアプリケーションが最後に読み取った値と一致しない場合、書き込みが失敗する原因となる条件が書き込みごとに追加されます。この動作により、アイテムの更新を楽観的ロックに効果的に適用できます。最初のプロセスが項目を読み取ってから更新を書き込むまでの間に、別のプロセスが項目を更新すると、書き込みは失敗します。

アイテムのバージョン番号を追跡するために使用する属性を指定するには、テーブルスキーマの数値属性にタグを付けます。

次のスニペットでは、version 属性がアイテムのバージョン番号を保持するように指定しています。

@DynamoDbVersionAttribute public Integer getVersion() {...}; public void setVersion(Integer version) {...};

これと同等の静的テーブルスキーマのアプローチは、次のスニペットで示されます。

.addAttribute(Integer.class, a -> a.name("version") .getter(Customer::getVersion) .setter(Customer::setVersion) // Apply the 'version' tag to the attribute. .tags(VersionedRecordExtension.AttributeTags.versionAttribute())

AtomicCounterExtension

AtomicCounterExtension はデフォルトでロードされ、レコードがデータベースに書き込まれるたびにタグ付きの数値属性が増えます。開始値と増分値を指定できます。値を指定しない場合、開始値は 0 に設定され、属性の値は 1 ずつ増加します。

どの属性がカウンターかを指定するには、テーブルスキーマのタイプ Long の属性にタグを付けます。

次のスニペットは、counter 属性のデフォルトの開始値と増分値の使用方法を示しています。

@DynamoDbAtomicCounter public Long getCounter() {...}; public void setCounter(Long counter) {...};

次のスニペットは、静的テーブルスキーマのアプローチを示しています。アトミックカウンタ拡張機能は、開始値を 10 に設定し、レコードが書き込まれるたびに値を 5 ずつ増やします。

.addAttribute(Integer.class, a -> a.name("counter") .getter(Customer::getCounter) .setter(Customer::setCounter) // Apply the 'atomicCounter' tag to the attribute with start and increment values. .tags(StaticAttributeTags.atomicCounter(10L, 5L))

AutoGeneratedTimestampRecordExtension

AutoGeneratedTimestampRecordExtension は、アイテムがデータベースに正常に書き込まれるたびに、そのタイプ Instant のタグ付き属性を現在のタイムスタンプで自動的に更新します。

このエクステンションはデフォルトではロードされません。そのため、このトピックの最初の例で示したように、拡張クライアントをビルドするときには、この拡張をカスタム拡張機能として指定する必要があります。

現在のタイムスタンプで更新する属性を指定するには、テーブルスキーマの Instant 属性にタグを付けます。

次のスニペットでは、lastUpdate 属性が拡張機能の動作の対象となります。属性は Instant タイプでなければならないという要件に注意してください。

@DynamoDbAutoGeneratedTimestampAttribute public Instant getLastUpdate() {...} public void setLastUpdate(Instant lastUpdate) {...}

これと同等の静的テーブルスキーマのアプローチは、次のスニペットで示されます。

.addAttribute(Instant.class, a -> a.name("lastUpdate") .getter(Customer::getLastUpdate) .setter(Customer::setLastUpdate) // Applying the 'autoGeneratedTimestamp' tag to the attribute. .tags(AutoGeneratedTimestampRecordExtension.AttributeTags.autoGeneratedTimestampAttribute())

カスタム拡張機能

次のカスタム拡張クラスは、更新式を使用する beforeWrite() メソッドを示しています。2 行目のコメントの後に、データベース内の項目にまだ registrationDate 属性がない場合に registrationDate 属性を設定するための SetAction を作成します。Customer オブジェクトが更新されるたびに、拡張機能は registrationDate が設定されていることを確認します。

public final class CustomExtension implements DynamoDbEnhancedClientExtension { // 1. In a custom extension, use an UpdateExpression to define what action to take before // an item is updated. @Override public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite context) { if ( context.operationContext().tableName().equals("Customer") && context.operationName().equals(OperationName.UPDATE_ITEM)) { return WriteModification.builder() .updateExpression(createUpdateExpression()) .build(); } return WriteModification.builder().build(); // Return an "empty" WriteModification instance if the extension should not be applied. // In this case, if the code is not updating an item on the Customer table. } private static UpdateExpression createUpdateExpression() { // 2. Use a SetAction, a subclass of UpdateAction, to provide the values in the update. SetAction setAction = SetAction.builder() .path("registrationDate") .value("if_not_exists(registrationDate, :regValue)") .putExpressionValue(":regValue", AttributeValue.fromS(Instant.now().toString())) .build(); // 3. Build the UpdateExpression with one or more UpdateAction. return UpdateExpression.builder() .addAction(setAction) .build(); } }