简体   繁体   中英

How do I handle an empty java set of strings in AWS DynamoDB

I'm trying to store an array of strings within an AWS DynamoDB table. For the most part this array will be populated with at least one string. However there is the case where the array could be empty.

I've created a DynamoDB model in a Java Lambda function that has a set of strings as one of it's properties. If I try to save a DynamoDB model when the set of strings is empty it gives me an error saying I can't store an empty set in DynamoDB.

So my question is, how would handle removing that set property when it's empty from my model before I save / update it in the DynamoDB?

Here's an example of the model.

@DynamoDBTable(tableName = "group")
public class Group {
    private String _id;
    private Set<String> users;

    @Null
    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    public String getId() {
        return _id;
    }

    public void setId(final String id) {
        _id = id;
    }

    @DynamoDBAttribute
    public Set<String> getUsers(){
        return users;
    }

    public void setUsers(final Set<String> users) {
        this.users = users;
    }

    public void addUser(String userId) {
        if(this.users == null){
            this.setUsers(new HashSet<String>(Arrays.asList(userId)));
        }else{
            this.getUsers().add(userId);
        }
   }
}

First time when I will create a group. It could have no user, or it could have one or more user.

This is somewhat of an old question but the way I would solve this problem is with a custom DynamoDBMarshaller .

Making use of the @DynamoDBMarshalling annotation, you can decorate the POJO accessor methods in order to dictate to the DynamoDB mapper which marshaller class to use to serialize and deserialize the set of strings. This way you get control over the special use cases.

Here is also a link to an AWS blog post with an example

The one caveat with the approach above is the customer marshaller solution serializes and deserializes to/from string so the representation in the database wouldn't be a set per se. However, I wouldn't consider that to be too bad.

Another approach might be to use the Document API , instead of the object mappers, which gives you full control over the items. Though I would still go for custom mapper with string backing.

When it came down to the actual problem it was because the code I inherited had the SaveBehavior on the DynamoDBMapperConfig set to UPDATE_SKIP_NULL_ATTRIBUTES which skips null values and therefore will never remove them from DynamoDB. See this post of explanations of all the different save behaviors. https://java.awsblog.com/post/Tx1MH3BFPW8FX6W/Using-the-SaveBehavior-Configuration-for-the-DynamoDBMapper

To elaborate on this a little bit further.

I'm setting my DynamoDBMapperConfig.SaveBehavior as such within my JAVA project.

_dynamoDBMapperConfig = new DynamoDBMapperConfig.Builder() .withSaveBehavior(SaveBehavior.UPDATE) .withTableNameResolver(TABLE_NAME_RESOLVER) .withConversionSchema(ConversionSchemas.V2) .build();

Then whenever you update a model that has a mapped @DynamoDBAttribute you also need to set the particular value to (null).

user.setFirstName(null)

This was the easiest way I found to be able to remove attributes from a DynamoDB Entry.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM