我尝试在更新DynamoDB中的记录之前设置乐观版本检查。但是当没有哈希键存在时,我一直从保存第一项中获取ConditionalCheckFailedException
。
有人可以告诉我我的代码有什么问题吗?
这是我的代码
final DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
builder.setConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT);
builder.setTableNameOverride(new DynamoDBMapperConfig.TableNameOverride(tableName));
DynamoDBMapperConfig mapperConfig = builder.build();
this.dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB, mapperConfig);
@Data
@DynamoDBTable(tableName = "OVERRIDE_AT_RUNTIME")
public class ItemRecord
{
public static final String CONTENT_ID = "content_id";
public static final String ACTION_COUNT = "action_count";
private static final String VERSION = "version";
@DynamoDBHashKey(attributeName = CONTENT_ID)
private String contentId;
@DynamoDBAttribute(attributeName = ACTION_COUNT)
private int actionCount;
@DynamoDBVersionAttribute(attributeName = VERSION)
private long version;
public TitleMatchProgressRecord() {}
public TitleMatchProgressRecord(final String contentId)
{
this.contentId = contentId;
this.actionCount = 0;
}
@DynamoDBIgnore
public void incrementActionCount()
{
actionCount++;
}
}
try {
ItemRecord itemRecord = loadRecord(contentId);
if (itemRecord == null) { // first item
itemRecord = new ItemRecord(contentId);
itemRecord.incrementActionCount();
DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression();
final Map<String, ExpectedAttributeValue> expectedAttributes = new HashMap<>();
expectedAttributes.put(ItemRecord.CONTENT_ID, new ExpectedAttributeValue(false));
saveExpression.setExpected(expectedAttributes);
dynamoDBMapper.save(itemRecord, saveExpression);
} else {
itemRecord.incrementActionCount();
itemRecord.resetLastModifiedAt();
dynamoDBMapper.save(itemRecord);
}
} catch (ConditionalCheckFailedException e) {
// retry
}
错误跟踪:
[testng] com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException: The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: UV4V9BSIE78ETRQC9LG4BOB23; Proxy: null)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1811)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1395)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1371)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1145)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:802)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:770)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:744)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:704)
[testng] at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:686)
[testng] at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:550)
[testng] at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:530)
[testng] at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.doInvoke(AmazonDynamoDBClient.java:5110)
[testng] at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:5077)
[testng] at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.executeUpdateItem(AmazonDynamoDBClient.java:4696)
[testng] at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.updateItem(AmazonDynamoDBClient.java:4662)
[testng] at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.doUpdateItem(DynamoDBMapper.java:871)
[testng] at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$2.executeLowLevelRequest(DynamoDBMapper.java:611)
[testng] at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.execute(DynamoDBMapper.java:750)
[testng] at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.save(DynamoDBMapper.java:640)
[testng] at com.amazonaws.services.dynamodbv2.datamodeling.AbstractDynamoDBMapper.save(AbstractDynamoDBMapper.java:123)
要在DynamoDB中进行“乐观锁定”,您需要在项目上保留一个版本属性-称为“动作计数”。如果有可能该项目尚不存在,并且需要首次创建-您必须明确处理这种情况。您不能仅仅假设项目始终存在并且具有先前的操作计数...例如,您可以执行以下操作:
读取项目(您可以通过更便宜的“最终一致性”进行读取)。该项目以前可能不存在-很好。
根据您所阅读的内容,创建该项目的新版本。如果该项目存在,则将“动作计数”加1,否则将动作计数设置为0。
使用条件表达式执行写入。如果该项目先前存在,则该条件应要求操作计数仍等于其读取(预递增)值。如果该项目以前不存在,则条件应该是该项目不存在。
如果条件更新在失败的条件下失败,请转到1重试。
[请注意,如果两个并发写入尝试创建一个新项目,一个将成功创建它(操作计数为0,而另一个则需要重试并实际更新该项目(最终导致操作计数为1)。] >