AWS Developer Blog

Using the SaveBehavior Configuration for the DynamoDBMapper

by Wade Matveyenko | on | in Java | Permalink | Comments |  Share

The high-level save API of DynamoDBMapper provides a convenient way of persisting items in an Amazon DynamoDB table. The underlying implementation uses either a PutItem request to create a new item or an UpdateItem request to edit the existing item. In order to exercise finer control over the low-level service requests, you can use a SaveBehavior configuration to specify the expected behavior when saving an item. First, let’s look at how to set a SaveBehavior configuration. There are two ways of doing it:

  • You can specify the default SaveBehavior when constructing a new mapper instance, which will affect all save operations from this mapper:

    // All save operations will use the UPDATE behavior by default
    DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient, 
                            new DynamoDBMapperConfig(SaveBehavior.UPDATE));
  • You can also force a SaveBehavior for a particular save operation:

    // Force this save operation to use CLOBBER, instead of the default behavior of this mapper
    mapper.save(obj, new DynamoDBMapperConfig(SaveBehavior.CLOBBER));

The next step is to understand different SaveBehavior configurations. There are four different configurations you can choose from: UPDATE(default), UPDATE_SKIP_NULL_ATTRIBUTES, CLOBBER, and APPEND_SET. When you add a new item to the table, using any of the four configurations has the same effect—puts the item as specified in the POJO (though it might be achieved by different service request calls). However, when it comes to updating an existing item, these SaveBehavior configurations have different results, and you need to choose the appropriate one according to how you want to control your data. In order to explain this, let’s walk through an example of using different SaveBehavior configurations to update an item specified by the same POJO:

  • Table schema:

    AttributeName key modeled_scalar modeled_set unmodeled
    KeyType Hash Non-key Non-key Non-key
    AttributeType Number String String set String
  • POJO class definition:

    @DynamoDBTable(tableName="TestTable")
    public class TestTableItem {
    
       private int key;
       private String modeledScalar;
       private Set<String> modeledSet;
    
       @DynamoDBHashKey(attributeName="key")
       public int getKey() { return key; }
       public void setKey(int key) { this.key = key; }
    
       @DynamoDBAttribute(attributeName="modeled_scalar")
       public String getModeledScalar() { return modeledScalar; }
       public void setModeledScalar(String modeledScalar) { this.modeledScalar = modeledScalar; }
    	
       @DynamoDBAttribute(attributeName="modeled_set")
       public Set<String> getModeledSet() { return modeledSet; }
       public void setModeledSet(Set<String> modeledSet) { this.modeledSet = modeledSet; }
    
    }
      
  • Existing item:

    {
         "key" : "99",
         "modeled_scalar" : "foo", 
         "modeled_set" : [
              "foo0", 
              "foo1"
         ], 
         "unmodeled" : "bar" 
    }
  • POJO object:

    TestTableItem obj = new TestTableItem();
    obj.setKey(99);
    obj.setModeledScalar(null);
    obj.setModeledSet(Collections.singleton("foo2");

Then let’s look at the effect of using each SaveBehavior configuration:

  • UPDATE (default)

    UPDATE will not affect unmodeled attributes on a save operation, and a null value for the modeled attribute will remove it from that item in DynamoDB.

    Updated item:

    {
         "key" : "99",
         "modeled_set" : [
              "foo2"
         ],
         "unmodeled" : "bar" 
    }
  • UPDATE_SKIP_NULL_ATTRIBUTES

    UPDATE_SKIP_NULL_ATTRIBUTES is similar to UPDATE, except that it ignores any null value attribute(s) and will NOT remove them from that item in DynamoDB.

    Updated item:

    {
         "key" : "99",
         "modeled_scalar" : "foo",
         "modeled_set" : [
              "foo2"
         ], 
         "unmodeled" : "bar" 
    }
  • CLOBBER

    CLOBBER will clear and replace all attributes, including unmodeled ones, (delete and recreate) on save.

    Updated item:

    {
         "key" : "99", 
         "modeled_set" : [
              "foo2"
         ]
    }
  • APPEND_SET

    APPEND_SET treats scalar attributes (String, Number, Binary) the same as UPDATE_SKIP_NULL_ATTRIBUTES does. However, for set attributes, it will append to the existing attribute value, instead of overriding it.

    Updated item:

    {
         "key" : "99",
         "modeled_scalar" : "foo",
         "modeled_set" : [
              "foo0", 
              "foo1", 
              "foo2"
         ], 
         "unmodeled" : "bar" 
    }

Here is a summary of the differences between these SaveBehavior configurations:

SaveBehavior On unmodeled attribute On null-value attribute On set attribute
UPDATE keep remove override
UPDATE_SKIP_NULL_ATTRIBUTES keep keep override
CLOBBER remove remove override
APPEND_SET keep keep append

As you can see, SaveBehavior provides great flexibility on how to update your data in Amazon DynamoDB. Do you find these SaveBehavior configurations easy to use? Are there any other save behaviors that you need? Leave your comment here and help us improve our SDK!