我是DynamoDB的新手,正在尝试使用事务支持的示例方案。我正在使用dynamodb事务库中提供的相同实体。唯一的不同是,我使用哈希键添加了范围键。这是表的定义:
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;
}
}
如您所见,我也在使用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
看起来它与版本有关,但不确定我在哪里出错。任何指针将不胜感激。
-谢谢
沙米克
最佳答案
Dynamodb具有Optimistic Locking的概念,该策略可确保您要更新(或删除)的客户端项目与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开始重试。这是先读然后写。
关于java - Dynamodb ConditionalCheckFailedException上的读取/更新操作-Java SDK,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26533223/