Spring Data DynamoDB

I have been working on a new micro-services platform at work leveraging AWS DynamoDB. We needed a way to store and retrieve data from DynamoDB in our Java micro services, but we were pretty hesitant about giving up the spring-data functionality. So, instead of directly using the AWS provided Java library we found the spring-data-dynamodb library. The spring-data-dynamodb library hooks into the spring-data framework and provides a mechanism to save and load data from a DynamoDB table through the use of a spring-data repository.

Spring Data

At first glance, it may seem silly to pass on the AWS library itself to use a third party library that is buried fairly deep under the spring-data library, but that may be because you aren’t familiar with how spring-data works. Spring-data allows the developer to extend a few different interfaces like: CrudRepository or PagingAndSortingRepository. At runtime, spring-data will then provide a concrete implementation for the service to use.

For example, we have configured spring-data to use spring-data-dynamodb module implementation in our service (there are many modules that support JPA, Mongo, Redis, etc). Given a domain model and repository like this:

@DynamoDBTable( tableName = "user" )
public class User {

    @Id
    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String id;

    @DynamoDBIndexHashKey(globalSecondaryIndexName = "idx_global_emailAddress")
    private String emailAddress;
    private String firstName;
    private String lastName;

    public User(String id, String emailAddress, String firstName, String lastName) {
        this.id = id;
        this.emailAddress = emailAddress;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public string getId() {
        return id;
    }

    public string setId(string id) {
        this.id = id;
    }

    public string getEmailAddress() {
        return emailaddress;
    }

    public string setEmailAddress(string emailaddress) {
        this.emailaddress = emailaddress;
    }

    public string getFirstName() {
        return firstname;
    }

    public string setFirstName(string firstname) {
        this.firstname = firstname;
    }

    public string getLastName() {
        return lastname;
    }

    public string setLastName(string lastname) {
        this.lastname = lastname;
    }
}

public interface UserRepository extends CrudRepository<User, String> {}

Then spring-data at runtime will instantiate the concrete implementation of the CrudRepository from the spring-data-dynamodb library for us. We are automatically provided with implementations of the following methods from CrudRepository:

This is pretty great, but the magic really comes from the dynamic query generation that spring-data enables and spring-data-dynamodb has implemented.

Spring Data Query Generation

Here comes the magic! Spring data has functionality that takes a method name and splits it into different parts. These parts are then feed to the configured module and it is up to the module to generate a valid query from the method name. The support can vary wildly depending upon which module is being used. Obviously, there are no stored procedures in DynamoDB so spring-data-dynamodb cannot support named queries, but it does provide the ability to dynamically generate a query based upon a Hash and Range key for either the table or a global secondary index.

To build on the previous example, we can add a method to the UserRepository to query by email address like this:

public interface UserRepository extends CrudRepository<User, String> {
    public List<Customer> findByEmailAddress(String emailAddress);
}

Since we have a global secondary index on the emailAddress field in the User object above this is a method that spring-data-dynamodb can generate a query on. Spring data supports quite a wide variety of syntax when writing out your method name. Syntax like: “findBy”, “queryBy”, “and”, “or”, “between”, “greaterthan”, and the list goes on and on. It really depends on each module which specific words are supported or not. You can find some information on what spring-data-dynamodb supports here.

This feature is just amazing and the amount of time and effort that it completely removes when writing queries to the database is astounding.

Spring Data DynamoDB

This library is really great and I have really been enjoying using it over the last few months. I’ve tried to get involved by helping with minor bug fixes and adding content to the wiki. There are definitely a few items to be aware of when using this library like:

Any help on the library would definitely be appreciated whether it is helping with documentation in the wiki, writing integration or unit tests, or even fixing bugs. The library maintainer has been really great at responding to my issues and has been extremely patient when dealing with the same issues over and over again…it appears that I wasn’t the only person having a problem with the Hash and Range key based tables. Thanks for all your help Sebastian!