Conditional update of DynamoDB record using DynamoDBMapper
Sometimes we need to update DynamoDB record only when specific conditions met for existing record of DynamoDB.
Let’s say you have below SampleTable DynamoDB entity/model class:
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@DynamoDBTable(tableName = "sampletable")
public class SampleTable {
private String hashKeyAttribute;
private String rangeKeyAttribute;
private Integer otherAttribute;
@DynamoDBHashKey(attributeName = "hash_key_attribute")
public String getHashKeyAttribute() {
return hashKeyAttribute;
}
@DynamoDBRangeKey(attributeName = "range_key_attribute")
public String getRangeKeyAttribute() {
return rangeKeyAttribute;
}
@DynamoDBAttribute(attributeName = "other_attribute")
public Integer getOtherAttribute() {
return otherAttribute;
}
}
Now, you have a use case to update sampletable only if other_attribute value of existing records is 2 or 5 or 7.
This can be achieved using DynamoDBSaveExpression. Please refer below Java example:
package com.dynamo.db.examples.service;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBSaveExpression;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue;
import com.dynamo.db.examples.SampleTable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DynamoDBConditionalManipulation {
public static void main(String[] args) {
try {
AmazonDynamoDB dynamoDBClient = AmazonDynamoDBClientBuilder.standard()
.withRegion(Regions.US_EAST_1)
.build();
DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient);
SampleTable sampleTableRecord = SampleTable.builder()
.hashKeyAttribute("hash_key")
.rangeKeyAttribute("range_key")
.otherAttribute(1)
.build();
// update record only if it exists and other_attribute value is 2 or 5 or 7 only
List<AttributeValue> expectedAttributeValues = Arrays.asList(
new AttributeValue().withN("2"),
new AttributeValue().withN("5"),
new AttributeValue().withN("7")
);
// create save expectedAttributesMap
Map expectedAttributeValuesMap = new HashMap();
expectedAttributeValuesMap.put(
"other_attribute",
new ExpectedAttributeValue()
.withAttributeValueList(expectedAttributeValues)
.withComparisonOperator(ComparisonOperator.IN));
// create save expression
DynamoDBSaveExpression dynamoDBSaveExpression = new DynamoDBSaveExpression();
dynamoDBSaveExpression.setExpected(expectedAttributeValuesMap);
saveDataInDynamoDBWithSaveExpressions(dynamoDBMapper, sampleTableRecord, dynamoDBSaveExpression);
System.out.println("Record saved successfully!");
} catch (Exception ex) {
// handle exception
}
}
public static <R> void saveDataInDynamoDBWithSaveExpressions(DynamoDBMapper dynamoDBMapper,
R recordToSave,
DynamoDBSaveExpression dynamoDBSaveExpressions) {
try {
dynamoDBMapper.save(recordToSave, dynamoDBSaveExpressions);
} catch (ConditionalCheckFailedException ex) { // thrown while dynamoDBSaveExpressions validation fails
// handle exception
} catch (Exception ex) {
// handle exception
}
}
}
Gradle dependency required is:
implementation group: 'com.amazonaws', name: 'aws-java-sdk-dynamodb', version: '1.11.+'
You can also use CONTAINS, BETWEEN, GT, LS, EQ, BEGINS_WITH etc as a comparison operator.
ConditionalCheckFailedException will be thrown if any of the ExpectedAttributeValue’s validation fails.
Thank you for reading, please follow if you like the article.
Subscribe to stay tuned for upcoming articles.