本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用擴充功能自訂 DynamoDB 增強型用戶端操作
DynamoDB 增強型用戶端 API 支援外掛程式擴充功能,可提供映射操作以外的功能。延伸模組使用兩種掛接方法來修改讀取和寫入操作期間的資料:
beforeWrite()
- 在寫入操作發生之前對其進行修改afterRead()
- 修改讀取操作發生後的結果
有些操作 (例如項目更新) 同時執行寫入和讀取,因此會呼叫這兩種勾點方法。
如何載入延伸模組
延伸項目會依照您在增強型用戶端建置器中指定的順序載入。負載順序可能很重要,因為一個延伸模組可以對先前延伸模組轉換的值採取行動。
根據預設,增強型用戶端會載入兩個延伸模組:
VersionedRecordExtension
- 提供樂觀鎖定AtomicCounterExtension
- 自動遞增計數器屬性
您可以使用增強型用戶端建置器覆寫預設行為,並載入任何延伸。如果您不想要預設副檔名,也可以不指定任何副檔名。
重要
如果您載入自己的擴充功能,增強型用戶端不會載入任何預設擴充功能。如果您想要任一預設延伸模組提供的行為,您需要將其明確新增至延伸模組清單。
下列範例顯示如何載入名為 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())
運作方式
使用 的樂觀鎖定對這些 DynamoDbEnhancedClient
和 DynamoDbTable
方法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))