DynamoDB Mapper Load Example and Explanation

Trying to figure out how to perform Load or ‘GetIItem’ requests on your AWS DynamoDB Table using DynamoDB Mapper? This is the article for you.

This is a continuation of my DynamoDBMapper series. Last time we talked about DynamoDB Query operations. In this post, we’re going to talk about Load operations, which behind the scenes, use the GetItem api.

As a reminder, the load api allows us to get a single item in an API call that has a specific hash key (or hash key + range key if thats the schema format you’re using). If you’re trying to get multiple records with the same hash key, and multiple range keys, you want to use query. And if you want to retrieve records with different hash keys (and possibly differnent

So let’s get started.

To perform a query on DynamoDB with DynamoDB Mapper, there a couple of small pre-requisites:

  1. You need IAM user credentials with dynamodb:getitem permissions
  2. A dependency on the on the AWS SDK which includes DynamoDBMapper (I suggest Maven for Java dependency management)

Starting State

We’re going to use the same table we normally use, one called CustomerOrders that is hydrated with items as seen below:

Starting State – My DynamoDB CustomerOrders table

I also have a model file called CustomerOrder.java and that defines our java representation of our DynamoDB items.

Its contents are below:

@ToString
@NoArgsConstructor //You need a empty default constructor
@Getter
@Setter
@DynamoDBTable(tableName = "CustomerOrders")
public class CustomerOrder {
    @DynamoDBHashKey(attributeName = "CustomerID")
    private String customerID;

    @DynamoDBRangeKey(attributeName = "OrderID")
    private String orderID;

    @DynamoDBAttribute(attributeName = "OrderAddress")
    private String orderAddress;

    @DynamoDBAttribute(attributeName = "OrderTotal")
    private Long orderTotal;
}

We also make use of the DynamoDB Client, which is instantiated like this:

//Specify credential details
AWSCredentialsProvider credentials = new AWSStaticCredentialsProvider(
        new BasicAWSCredentials(System.getenv("ACCESS_KEY"),
                                System.getenv("SECRET_ACCESS_KEY")));

//Create client
AmazonDynamoDB ddbClient = AmazonDynamoDBClientBuilder.standard()
        .withCredentials(credentials)
        .withRegion("us-east-1") //Remember to change your region!
        .build();

DynamoDBMapper mapper = new DynamoDBMapper(ddbClient);

Now we’re ready to perform our Load operation.

Performing Load on DynamoDB

Firstly, here’s the code we’re using to run the load.

CustomerOrder customerOrder = new CustomerOrder();
customerOrder.setCustomerID("CUSTOMER3");
customerOrder.setOrderID("5"); //RangeKey is REQUIRED for load

CustomerOrder result = mapper.load(customerOrder,
                                   new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT));

System.out.println(result);

The result of the println yields the following:

CustomerOrder(customerID=CUSTOMER3, orderID=5, orderAddress=123 Main St, orderTotal=7.11)

Lets discuss whats going on in the code.

Initially, we’re setting the properties on our CustomerOrder object. Adding values to the input object indicates to DynamoDB that this is the item I am looking for. So in our example, we will be retrieving a CustomerOrder record that has a CustomerID of “CUSTOMER3” and a OrderID of 5.

Note that since our DynamoDB table configuration includes a RangeKey (OrderID in this case), we MUST provide its value in the input object. Failure to do so will result in a DynamoDB exception thrown back at you. If you don’t use a range key in your table, then don’t worry about this.

If you don’t know the RangeKey value, you should use the Query operation which will return all values with the same HashKey (CustomerID in this case). From there, you can filter the results down in your application layer.

After setting the input object properties, we call the DynamoDBMapper load function. We provide it the input object, and optionally, a second parameter called DynamoDBMapperConfig. Setting the ConsistentReads to CONSISTENT in this case tells DynamoDB that when we attempt to retrieve this value, it must be replicated across all the nodes in DynamoDB (and therefore, the most ‘correct’ value). This is mostly important for those of you that use read-after-write or have a requirement that must ensure we are always operating on the most up to date data. Keep in mind, there is additional cost (and performance implications) of using consistent reads. You can learn more about it here.

You may enjoy my YouTube video on DynamoDB Schema Design: Choosing the Right Key.

This setting has to do with the way DynamoDB stores data redundantly. It will replicate your data onto multiple availability zones. Alternatively, we can use eventual consistency which is indicated by setting ConsistentReads.EVENTUAL.

Eventual consistency on the other hand can result in potentially stale data. If you have a use case where stale data is OK, or you have a scenario where you write very less often than you read to a particular row, you should be fine with using eventual.

To learn more about how to use load operations, you can check out DynamoDB’s documentation here or my YouTube video on DynamoDBMapper save/load/query/delete here.

Exit mobile version