DynamoDBMapper save only if object doesn't exist

14,897

Solution 1

I believe you should be able to do this with a DynamoDbSaveExpression object that can apply to the mapper.

There's a tutorial on the AWS site here, code shown below:

try {
    DynamoDBSaveExpression saveExpression = new       DynamoDBSaveExpression();
    Map expected = new HashMap();
    expected.put("status", new ExpectedAttributeValue().withExists(false));

    saveExpression.setExpected(expected);

    mapper.save(obj, saveExpression);
} catch (ConditionalCheckFailedException e) {
    // This means our save wasn't recorded, since our constraint wasn't met
    // If this happens, the worker can simply look for a new task to work on
}

Solution 2

Here's the correct way to implement this with the DynamoDBMapper:

User newUser = new User();
newUser.setUsername(username);
newUser.setPassword(password);

DynamoDBSaveExpression saveExpr = new DynamoDBSaveExpression();
saveExpr.setExpected(new ImmutableMap.Builder()
.put("username", new ExpectedAttributeValue(false)).build());

dynamoDBMapper.save(newUser, saveExpr);

Source: https://blog.jayway.com/2013/08/24/create-entity-if-not-exists-in-dynamodb-from-java/

EDIT: Here's my implementation of it in practice. Extremely easy to implement:

public Statement saveIfNotExist(Statement statement) throws ConditionalCheckFailedException {
    return mapper.save(statement, new DynamoDBSaveExpression().withExpected(ImmutableMap.of("id", new ExpectedAttributeValue(false))));
}

with passing unit test:

@Test(expectedExceptions = ConditionalCheckFailedException.class)
public void shouldNotProcessIdenticalStatementUpdateInstances() {
    Statement statement1 = StatementTestBuilder.valid().build();
    Statement statement2 = StatementTestBuilder.valid().withId(statement1.getId()).build();

    statementRepository.saveIfNotExist(statement1);
    statementRepository.saveIfNotExist(statement2);
}
Share:
14,897
Nosrettap
Author by

Nosrettap

I recently graduated from Duke University as a computer science and economics double major. I am now working full time as a software developer. I am proficient in Objective-C and Java, and I know (to some degree) C, C++, Python, Perl, SML, Assembly, HTML, CSS, JavaScript.

Updated on June 20, 2022

Comments

  • Nosrettap
    Nosrettap almost 2 years

    Using the Java DynamoDBMapper, how can I save an object only if it doesn't already exist (based on primary key). If it does exist, I want an exception or failure to be thrown, rather than having the existing entry updated.

  • aalosious
    aalosious over 7 years
    shouldn't it be withExists(false)?
  • Sebastian D'Agostino
    Sebastian D'Agostino almost 7 years
    A parenthesis is missing after ("READY") Here is the correct line: expected.put("status", new ExpectedAttributeValue(new AttributeValue("READY")).withExists(true));
  • Corin
    Corin almost 6 years
    -1 as this answer only saves when the item already exists in the table. This is the opposite of the result desired by the question.
  • tddmonkey
    tddmonkey almost 6 years
    changed to fix the boolean state (oops)
  • juan.facorro
    juan.facorro over 5 years
    Edited the answer since when using .withExists(false) there must not be a value provided.
  • ufdeveloper
    ufdeveloper over 5 years
    Does this make an additional read on the table? I believe it does!
  • tddmonkey
    tddmonkey over 5 years
    No - it's all handled during the write