11

I'm new to DynamoDB and trying out a sample scenario using Transaction support. I'm using the same entity provided in dynamodb-transaction library. Only difference is I've added a range key with the hash key. Here's the table definition:

  • ItemId --> hash key , string
  • ItemName --> range key, string

@DynamoDBTable(tableName = "Item")
public static class ExampleItem {
    private String itemId;
    private String value;
    private String itemName;
    private Long version;
    @DynamoDBHashKey(attributeName = "ItemId")
    public String getItemId() {
        return itemId;
    }
    public void setItemId(String itemId) {
        this.itemId = itemId;
    }
    @DynamoDBRangeKey(attributeName="ItemName")
    public String getItemName() {
        return itemName;
    }
    public void setItemName(String itemName) {
        this.itemName = itemName;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    @DynamoDBVersionAttribute
    public Long getVersion() {
        return version;
    }
    public void setVersion(Long version) {
        this.version = version;
    }
}

As you can see, I'm using the version attribute as well. Now, I'm trying to execute a simple create or update scenario using transaction/dbmapper. Here's the code snippet.

Transaction t1 = txManager.newTransaction();
ExampleItem keyItem = new ExampleItem();
keyItem.setItemId("Item1");
keyItem.setItemName("USA");
ExampleItem item = t1.load(keyItem);
if (item != null) {
    item.setValue("Magenta");
    item.setItemName("UK");
    t1.save(item);
} else {
    item = new ExampleItem();
    item.setItemId(keyItem.getItemId());
    item.setItemName("USA");
    item.setValue("Violet");
    t1.save(item);
}
t1.commit();
t1.delete();

I'm able to add the record without any issue, but I'm having a problem when I'm trying to read the record and update any attribute. I'm getting the following exception:

Uncaught exception:com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: Item {ItemId={S: Item1,}, ItemName={S: UK,}} had unexpected attributes: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: expected attribute(s) {version={Value: {N: 1,},Exists: true}} but found null
com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: Item {ItemId={S: Item1,}, ItemName={S: UK,}} had unexpected attributes: Status Code: 0, AWS Service: null, AWS Request ID: null, AWS Error Code: null, AWS Error Message: expected attribute(s) {version={Value: {N: 1,},Exists: true}} but found null

Looks like it has something to do with version, but not sure where am I going wrong. Any pointers will be appreciated.

-Thanks

Shamik

4

3 に答える 3

3

Dynamodb にはOptimistic Lockingというこの概念があり、更新 (または削除) するクライアント側のアイテムが DynamoDB のアイテムと同じであることを保証する戦略です。

  1. 最初の保存:

初めての更新の場合は、この形式に従う必要があります

DynamodbSaveExpression saveExpression = 
       new DynamodbSaveExpression()
       .withExpectedEntry("ItemId", new ExpectedAttributeValue().withExists(false)
       .withConditionalOperator(AND)
       .withExpectedEntry("ItemName", new ExpectedAttributeValue().withExists(false));
// saving the item to dynamodb 
dynamodbmapper.save(itemToSave, saveExpression);

説明: 「ItemId」と「ItemValue」の両方の組み合わせが dynamodb に存在しない場合にのみ、itemToSaveを保存する必要があることを伝えています。

  1. 既存のアイテムへの更新:

dynamodb の既存の項目を更新するには、次の形式に従う必要があります

// Step1: Do a GET
ExampleItem itemInDynamo = dynamoDBMapper.load(ExampleItem.class, "item_id_value", "item_name_value");
// Step2: Get the version in Dynamo
Long versionInDynamo = itemInDynamo.getVersion();
DynamodbSaveExpression saveExpression = 
       new DynamodbSaveExpression()
       .withExpectedEntry("version", 
       new ExpectedAttributeValue(new AttributeValue().withN(versionInDynamodb.toString())));
// Step3: Update the item
dynamodbmapper.save(itemToSave, saveExpression);

保存に使用したバージョンが Dynamodb で同じ場合にのみ保存が成功します。そうでない場合は、保存がConditionalCheckFailedExceptionで失敗し、ステップ 1から再試行する必要があります。これは、最初に読み取り、次に書き込みます。

于 2017-07-19T14:45:25.750 に答える
1

通常、これはキーが dynamodb の複数の要素で同じである場合に発生します。たとえば、id が hashKey で、folderName が rangeKey のフォルダーがある場合、ハッシュ (hashkey+rangeKey) が同じになるフォルダーを再度保存することありませ

于 2016-10-05T11:40:05.130 に答える