【问题标题】:Dynamodb ConditionalCheckFailedException on read / update operation - java sdkDynamodb ConditionalCheckFailedException 读取/更新操作 - java sdk
【发布时间】:2014-10-23 16:50:20
【问题描述】:

我是 DynamoDB 的新手,正在尝试使用事务支持的示例场景。我正在使用 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;
    }
}

如您所见,我也在使用版本属性。 现在,我正在尝试使用事务/dbmapper 执行一个简单的创建或更新方案。这是代码sn-p。

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

看起来它与版本有关,但不确定我哪里出错了。任何指针将不胜感激。

-谢谢

沙米克

【问题讨论】:

  • 发现任何有用的东西?

标签: java amazon-web-services amazon-dynamodb aws-sdk


【解决方案1】:

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

解释:我们告诉 itemToSave 只有在 dynamodb 中没有“ItemId”、“ItemValue”组合时才应该保存。

  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 重试。这是先读后写。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      这通常发生在您的 keys 与 dynamodb 中的多个元素相同时。例如,如果您有 Folder,其中 id 为 hashKey,folderName 为 rangeKey,您将不会再次将 Folder 保存到您的 hash(hashkey+rangeKey)会是一样的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-11
        • 1970-01-01
        • 2020-05-02
        • 1970-01-01
        • 1970-01-01
        • 2014-09-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多