本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用擴展
DynamoDB 增強型用戶端 API 支援外掛程式擴充功能,可提供對應作業以外的功能。擴充功能有兩個掛接方法,beforeWrite()
以及afterRead()
. beforeWrite()
在寫操作發生之前修改寫操作,並在afterRead()
發生讀取操作之後修改該操作的結果。由於某些作業 (例如項目更新) 會同時執行寫入,然後執行讀取,因此會呼叫這兩個勾點方法。
擴充功能會依照在增強型用戶端產生器中指定的順序載入。載入順序很重要,因為一個延伸功能可以對先前延伸功能所轉換的值執行作用。
增強型用戶端 API 隨附一組位於extensions
套件中的外掛程式擴充功能。依預設,增強型用戶端會載入VersionedRecordExtension
和AtomicCounterExtension
. 您可以使用增強用戶端建置器覆寫預設行為,並載入任何擴充功能。如果您不想使用預設副檔名,也可以指定 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 行之後,我們創建一個SetAction
來設置registrationDate
屬性,如果數據庫中的項目還沒有registrationDate
屬性。每當更新Customer
物件時,擴充功能都會確保registrationDate
已設定 a。
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(); } }