使用DynamoDBSaveExpression来检查其他键的存在

时间:2018-11-24 05:22:19

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

作为一个简单的例子,我有一个看起来像这样的类:

public class DbData {
    @DynamoDBAutoGeneratedKey
    @DynamoDBHashKey(attributeName = "id")
    private UUID id;
    private UUID parent;
    // other fields ...
}

此类存储在DynamoDB表中。将新条目添加到表中后,我要确保已存在父项(如果已设置父项)。

可以使用DynamoDBSaveExpression完成此操作吗?

例如,我可以确保当前ID不存在:

new DynamoDBSaveExpression()
    .withExpectedEntry("id", new ExpectedAttributeValue().withExists(false));

我认为这可能有效,但是它无效:

    ExpectedAttributeValue expectedAttributeValue = new ExpectedAttributeValue(new AttributeValue(parent.toString()));
    dynamoDBSaveExpression = new DynamoDBSaveExpression()
            .withExpectedEntry("id", new ExpectedAttributeValue().withExists(false));
            .withExpectedEntry("id", expectedAttributeValue.withExists(true))
            .withConditionalOperator(ConditionalOperator.AND);

修改

有一个RESTful API,它定义了一个POST以创建资源,并且该资源作为条目存储在DynamoDB表中。

资源允许使用父标识符指定的层次结构。

如果未找到父资源,则返回404:

a. if parent identifier is set
b.     get parent resource from DynamoDB
c.     if parent not found
d.         return 404
e. persist resource in DynamoDB

伪代码不是原子的。 'b'可以返回父级,但是另一个线程/进程可以在'e'之前删除它。

我希望条件表达式在这里有所帮助。 transaction library是完成此任务的唯一方法吗?还是应该对数据进行不同的建模?

1 个答案:

答案 0 :(得分:0)

否,ConditionExpression无法查看除正在保存/更新/删除的当前项目以外的任何项目。

更新

如果可能的话,您是否可以以无法删除内容的方式设计数据? (也许您可以将其标记为已过时。)这完全消除了问题,因为一旦存在某些内容,它便始终存在。

如果这不可能,您可能需要查看DynamoDBLockClient。它提供了由DynamoDB支持的通用分布式锁定API。

您的新伪代码将是

a. if parent identifier is set
b.     Acquire lock for parent identifier
c.     get parent resource from DynamoDB
d.     if parent not found
e.         Release lock
f.         return 404
g. persist resource in DynamoDB
h. Release lock

此外,在任何要删除作为父标识符的内容的操作中,都应在删除该父标识符之前获得对该父标识符的锁定。如果这样做,则可以确保在创建子项的过程中不会删除父项。