Dynamodb ConditionalCheckFailedException 读取/更新操作 - java sdk
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26533223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamodb ConditionalCheckFailedException on read / update operation - java sdk
提问by Shamik
I'm new to DynamoDB and trying out a sample scenario using Transaction support. I'm using the same entity provided in dynamodb-transactionlibrary. Only difference is I've added a range key with the hash key. Here's the table definition:
我是 DynamoDB 的新手,正在尝试使用事务支持的示例场景。我正在使用dynamodb-transaction库中提供的相同实体。唯一的区别是我用散列键添加了一个范围键。这是表定义:
ItemId
--> hash key , stringItemName
--> range key, string
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;
}
}
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.
如您所见,我也在使用 version 属性。现在,我正在尝试使用事务/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();
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
沙米克
回答by user2001728
Looks like you need to set the version when creating the item class. It's expecting 1 but found null. The versionedAttribute is expecting a value, and it seems when the item is created for the first time it will expect 1.
看起来您需要在创建项目类时设置版本。它期待 1 但发现为空。versionedAttribute 需要一个值,似乎在第一次创建项目时它需要 1。
If you update this item in the future, it should take care of incrementing the version internally.
如果您将来更新此项目,它应该负责在内部增加版本。
回答by Rathan
Dynamodb has this concept of Optimistic Locking, is strategy to ensure that the client-side item that you are updating (or deleting) is the same as the item in DynamoDB.
Dynamodb 有这个Optimistic Locking 的概念,是确保您正在更新(或删除)的客户端项目与 DynamoDB 中的项目相同的策略。
- First save:
- 首先保存:
If it's a first update, you have to follow this format
如果是第一次更新,则必须遵循此格式
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);
Explanation: We are telling that itemToSaveshould be saved only when both "ItemId", "ItemValue" combination is not there in dynamodb.
说明:我们告诉您,仅当dynamodb 中不存在“ItemId”、“ItemValue”组合时才应保存 itemToSave。
- Update to an existing item:
- 更新现有项目:
For an update to an existing item in dynamodb, you have to follow this format
要更新 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);
Save will only succeed if the version with which you are saving is the same in the Dynamodb, if not save will fail with ConditionalCheckFailedExceptionthen you have retry from step1. This is Read first then Write.
仅当您保存的版本与 Dynamodb 中的版本相同时,保存才会成功,如果不是,保存将失败并出现ConditionalCheckFailedException,那么您必须从步骤 1 重试。这是先读后写。
回答by M-sAnNan
Usualy this occurs when your keysare same for more then one element in dynamodb. For example if you have Folderwith id as hashKey and folderName as rangeKey, You wont save the Folderagain where your hash(hashkey+rangeKey) would be same.
通常,当您的键对于 dynamodb 中的多个元素相同时会发生这种情况。例如,如果您的Folderid 为 hashKey,folderName 为 rangeKey,您将不会再次保存该文件夹,而您的哈希值(hashkey+rangeKey) 将相同。