读取/更新操作时发生Dynamodb ConditionalCheckFailedException

我是DynamoDB的新手,并尝试使用Transaction支持的示例场景。 我正在使用dynamodb-transaction库中提供的相同实体。 唯一的区别是我用散列键添加了一个范围键。 这里是表格定义:

  • ItemId - >散列键,字符串
  • ItemName - >范围键,字符串

  • @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;
        }
    }
    

    正如你所看到的,我也使用了版本属性。 现在,我正尝试使用transaction / dbmapper执行一个简单的创建或更新场景。 这是代码片段。

    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();
    

    我可以在没有任何问题的情况下添加记录,但在尝试读取记录和更新任何属性时遇到问题。 我收到以下例外情况:

    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
    

    看起来它与版本有关,但不知道我错在哪里。 任何指针将不胜感激。

    -谢谢

    Shamik


    看起来您需要在创建项目类时设置版本。 它期待1,但发现空。 versionedAttribute期待一个值,并且它看起来是该项目第一次创建时期望值为1。

    如果将来更新此项目,它应该负责在内部增加版本。


    Dynamodb具有乐观锁定的这一概念,是确保您正在更新(或删除)的客户端项目与DynamoDB中的项目相同的策略。

  • 先保存:
  • 如果这是第一次更新,则必须遵循此格式

    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);
    

    说明:我们告诉只有在dynamodb中没有“ItemId”,“ItemValue”组合时,才应保存itemToSave。

  • 更新到现有项目:
  • 要更新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步开始重试。 这是先读然后写。


    Usualy这种情况发生在您的密钥与dynamodb中的多个元素相同时。 例如,如果您将文件夹的id设置为hashKey,将folderName设置为rangeKey,则您不会再次将文件夹另存为您的散列 (hashkey + rangeKey)所在的位置。

    链接地址: http://www.djcxy.com/p/82221.html

    上一篇: Dynamodb ConditionalCheckFailedException on read / update operation

    下一篇: Declare array/hashmap in gradle.properties file