使用擴充功能自訂 DynamoDB 增強型用戶端操作 - AWS SDK for Java 2.x

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用擴充功能自訂 DynamoDB 增強型用戶端操作

DynamoDB 增強型用戶端 API 支援外掛程式擴充功能,可提供映射操作以外的功能。延伸模組使用兩種掛接方法來修改讀取和寫入操作期間的資料:

  • beforeWrite() - 在寫入操作發生之前對其進行修改

  • afterRead() - 修改讀取操作發生後的結果

有些操作 (例如項目更新) 同時執行寫入和讀取,因此會呼叫這兩種勾點方法。

如何載入延伸模組

延伸項目會依照您在增強型用戶端建置器中指定的順序載入。負載順序可能很重要,因為一個延伸模組可以對先前延伸模組轉換的值採取行動。

根據預設,增強型用戶端會載入兩個延伸模組:

您可以使用增強型用戶端建置器覆寫預設行為,並載入任何延伸。如果您不想要預設副檔名,也可以不指定任何副檔名。

重要

如果您載入自己的擴充功能,增強型用戶端不會載入任何預設擴充功能。如果您想要任一預設延伸模組提供的行為,您需要將其明確新增至延伸模組清單。

下列範例顯示如何載入名為 verifyChecksumExtension的自訂延伸模組VersionedRecordExtension。此範例中AtomicCounterExtension不會載入 。

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

可用的延伸模組詳細資訊和組態

下列各節提供 SDK 中每個可用延伸模組的詳細資訊。

使用 實作樂觀鎖定 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())

運作方式

使用 的樂觀鎖定對這些 DynamoDbEnhancedClientDynamoDbTable方法VersionedRecordExtension有下列影響:

putItem

新項目會獲指派初始版本值 0。這可以使用 設定@DynamoDbVersionAttribute(startAt = X)

updateItem

如果您擷取項目、更新其一或多個屬性,並嘗試儲存變更,則只有在用戶端和伺服器端的版本號碼相符時,操作才會成功。

如果成功,版本編號會自動遞增 1。這可以使用 設定@DynamoDbVersionAttribute(incrementBy = X)

deleteItem

DynamoDbVersionAttribute 註釋沒有效果。刪除項目時,您必須手動新增條件表達式。

下列範例新增條件式表達式,以確保已刪除的項目是已讀取的項目。在下列範例中recordVersion, Bean 的 屬性以 標註@DynamoDbVersionAttribute

// 1. Read the item and get its current version. Customer item = customerTable.getItem(Key.builder().partitionValue("someId").build()); // `recordVersion` is the bean's attribute that is annotated with `@DynamoDbVersionAttribute`. AttributeValue currentVersion = item.getRecordVersion(); // 2. Create conditional delete with the `currentVersion` value. DeleteItemEnhancedRequest deleteItemRequest = DeleteItemEnhancedRequest.builder() .key(KEY) .conditionExpression(Expression.builder() .expression("recordVersion = :current_version_value") .putExpressionValue(":current_version_value", currentVersion) .build()).build(); customerTable.deleteItem(deleteItemRequest);
transactWriteItems
  • addPutItem:此方法具有與 相同的行為putItem

  • addUpdateItem:此方法具有與 相同的行為updateItem

  • addDeleteItem:此方法具有與 相同的行為deleteItem

batchWriteItem
  • addPutItem:此方法具有與 相同的行為putItem

  • addDeleteItem:此方法具有與 相同的行為deleteItem

注意

DynamoDB 全域資料表在並行更新之間使用「最後寫入器獲勝」對帳,其中 DynamoDB 會盡最大努力判斷最後寫入器。如果您使用全域資料表,此「上次寫入器獲勝」政策表示鎖定策略可能無法如預期運作,因為所有複本最終都會根據 DynamoDB 決定的上次寫入收斂。

如何停用

若要停用樂觀鎖定,請勿使用 @DynamoDbVersionAttribute註釋。

使用 實作計數器 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())

使用 AutoGeneratedUuidExtension 產生 UUID

AutoGeneratedUuidExtension 新記錄寫入資料庫時,延伸項目會產生屬性的唯一 UUID (通用唯一識別符)。使用 Java JDK UUID.randomUUID() 方法,並套用至類型 的屬性java.lang.String。預設不會載入此延伸模組。

組態

uniqueId 屬性是下列程式碼片段中延伸項目行為的目標。

@AutoGeneratedUuidExtension public String getUniqueId() {...} public void setUniqueId(String uniqueId) {...}

等效的靜態資料表結構描述方法會顯示在下列程式碼片段中。

.addAttribute(String.class, a -> a.name("uniqueId") .getter(Customer::getUniqueId) .setter(Customer::setUniqueId) // Applying the 'autoGeneratedUuid' tag to the attribute. .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute())

如果您希望延伸模組僅針對 putItem 方法填入 UUID,而非針對 updateItem方法填入 UUID,請新增更新行為註釋,如下列程式碼片段所示。

@AutoGeneratedUuidExtension @DynamoDbUpdateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS) public String getUniqueId() {...} public void setUniqueId(String uniqueId) {...}

如果您使用靜態資料表結構描述方法,請使用下列同等程式碼。

.addAttribute(String.class, a -> a.name("uniqueId") .getter(Customer::getUniqueId) .setter(Customer::setUniqueId) // Applying the 'autoGeneratedUuid' tag to the attribute. .tags(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute(), StaticAttributeTags.updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS))