Using Amazon DynamoDB Object Mapping (OM) with the AWS SDK for Android

Articles & Tutorials>Using Amazon DynamoDB Object Mapping (OM) with the AWS SDK for Android
This article summarizes the benefits of the new Object Mapper DynamoDBMapper.

Details

Submitted By: Yosuke@AWS
AWS Products Used: AWS SDK for Android, Amazon DynamoDB
Created On: May 23, 2012 9:19 PM GMT
Last Updated: September 25, 2014 8:20 PM GMT
Version 2 of the AWS Mobile SDK
  • This article and sample apply to Version 1 of the AWS Mobile SDK. If you are building new apps, we recommend you use Version 2. For details, please visit the AWS Mobile SDK page.
  • This content is being maintained for historical reference.

Amazon DynamoDB is a fast, highly scalable, highly available, cost-effective, non-relational database service. Amazon DynamoDB removes traditional scalability limitations on data storage while maintaining low latency and predictable performance.

The AWS SDK for Android supports Amazon DynamoDB, and this article discusses a new AWS SDK for Android add-on library that enables you to map your client-side classes to the Amazon DynamoDB tables. The individual object instances map to items in a table, and they enable you to perform various create, read, update, and delete (CRUD) operations on items, and to execute queries. Please review the User Preferences sample app to familiarize youreslf with using Amazon DynamoDB and Token Vending Machine (TVM) with the AWS SDK for Android.

The complete sample code and project files are included in the AWS SDK for Android. A link to the SDK is available at the end of this article.

Overview

In Amazon DynamoDB, a database is a collection of tables. A table is a collection of items, and each item is a collection of attributes. For this app, each item in the table represents an individual user. Each item has multiple attributes, which include the user's name and preferences. Each item also has a hash key�in this case, userNo�which is the primary key for the table. This item in Amazon DynamoDB will be mapped to a UserPreference Java object, and developers can directly manipulate the item through the UserPreference instance.

The app demonstrates how to add, modify, and remove users, and retrieve their preference data using Amazon DynamoDB OM. The Amazon DynamoDB object model (OM) does not provide APIs to create, update, or delete tables. Only the low-level APIs enable you to perform these operations. The User Preferences article discusses how to use the low-level APIs with the AWS SDK for Android.

Creating an Amazon DynamoDB Client and Mapper

To make low-level service requests to Amazon DynamoDB, you need to instantiate an Amazon DynamoDB client. In order to use the Amazon DynamoDB OM, you need to instantiate a DynamoDB Mapper object with the Amazon DynamoDB client. The code below shows how to create an Amazon DynamoDB OM using the stored temporary credentials from the TVM.

AWSCredentials credentials = AmazonSharedPreferencesWrapper
		.getCredentialsFromSharedPreferences(this.sharedPreferences);

AmazonDynamoDBClient ddb = new AmazonDynamoDBClient(credentials);
DynamoDBMapper mapper = new DynamoDBMapper(ddb);

Defining Mapping Class

You can map a class in your client app to the TestUserPereference table as shown in the following code example. The code snippet defines a UserPreference class and uses the annotations that are defined by Amazon DynamoDB to establish the mapping.

  • @DynamoDBTable identifies the target table in Amazon DynamoDB.
  • @DynamoDBHashKey maps a class property to the hash attribute of the table.
  • @DynamoDBAttribute maps a property to an item attribute.

NOTE: The DynamoDB OM provides the @DynamoDBVersionAttribute annotation type that you can use to enable optimistic locking that ensures that the client-side item that you are updating (or deleting) is the same as the item on the server-side. For more information on how to use optimistic locking with the DynamoDB OM, please read this Developer Guide. For a complete list of the annotations that the DynamoDB OM offers for you to map your classes and properties to tables and attributes, go to this topic.

@DynamoDBTable(tableName = "TestUserPereference")
public static class UserPreference {
	private int userNo;
	private String firstName;
	private String lastName;
	private Boolean autoLogin;
	private Boolean vibrate;
	private Boolean silent;
	private String colorTheme;

	@DynamoDBHashKey(attributeName = "userNo")
	public int getUserNo() {
		return userNo;
	}

	public void setUserNo(int userNo) {
		this.userNo = userNo;
	}

	@DynamoDBAttribute(attributeName = "firstName")
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	@DynamoDBAttribute(attributeName = "lastName")
	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@DynamoDBAttribute(attributeName = "autoLogin")
	public Boolean isAutoLogin() {
		return autoLogin;
	}

	public void setAutoLogin(Boolean autoLogin) {
		this.autoLogin = autoLogin;
	}

	@DynamoDBAttribute(attributeName = "vibrate")
	public Boolean isVibrate() {
		return vibrate;
	}

	public void setVibrate(Boolean vibrate) {
		this.vibrate = vibrate;
	}

	@DynamoDBAttribute(attributeName = "silent")
	public Boolean isSilent() {
		return silent;
	}

	public void setSilent(Boolean silent) {
		this.silent = silent;
	}

	@DynamoDBAttribute(attributeName = "colorTheme")
	public String getColorTheme() {
		return colorTheme;
	}

	public void setColorTheme(String colorTheme) {
		this.colorTheme = colorTheme;
	}
}

NOTE: Please note that userNo is primitive, and autoLogin, vibrate, and silent have nullable types. Primitives and nullable types behave differently with the DynamoDB OM. Nullable types that haven't been set will not be sent to the Amazon DynamoDB on a save(); on the other hand, primitives that haven't been set will be sent to the Amazon DynamoDB as their default values. Also, the version attributes must use nullable types. For this example app, userNo is a hash key that always has a value, so it's defined as a primitive value. autoLogin, vibrate, and silent are defined as nullable types so that it's easier to change their default values in the future. In general, using nullable types is recommended.

Creating Users (Item Creation)

For each user, we'll create an item in the table. An item is a collection of attribute/value pairs. For each item, we'll have three attributes: userNo, firstName, and lastName. With the low-level API, these are added to a put item request in order to create the item. With the Amazon DynamoDB OM, you instantiate a UserPreference object and set its attributes; then you can persist the object into the Amazon DynamoDB table by calling the save method on the DynamoDB Mapper. This simplifies the code and makes it more readable.

Low-level API Amazon DynamoDB OM
HashMap item =
		new HashMap();

AttributeValue userNo = new AttributeValue()
		.withN(String.valueOf(i));
item.put("userNo", userNo);

AttributeValue firstName = new AttributeValue()
		.withS(Constants.getRandomName());
item.put("firstName", firstName);

AttributeValue lastName = new AttributeValue()
		.withS(Constants.getRandomName());
item.put("lastName", lastName);

PutItemRequest request = new PutItemRequest()
		.withTableName(PropertyLoader
				.getInstance()
				.getTestTableName())
		.withItem(item);

ddb.putItem(request);
UserPreference userPreference = new UserPreference();
userPreference.setUserNo(i);
userPreference.setFirstName(Constants.getRandomName());
userPreference.setLastName(Constants.getRandomName());

mapper.save(userPreference);

Deleting Users (Item Deletion)

Removing a user from the list means deleting the corresponding item from the table. With the low-level API, we specify the item we want to delete using the hash key for the item. With the Amazon DynamoDB OM, you can simply call a delete method and pass a UserPreference object to the DynamoDB Mapper object.

Low-level API Amazon DynamoDB OM
Key primaryKey = new Key().withHashKeyElement(targetValue);
DeleteItemRequest request = new DeleteItemRequest()
		.withTableName(PropertyLoader
				.getInstance()
				.getTestTableName())
		.withKey(primaryKey);
		
ddb.deleteItem(request);
mapper.delete(deleteUserPreference);

Listing Users (Table Scan)

We can retrieve a collection of users with a scan request. A scan request simply scans the table and returns the results in an undetermined order.

The list returned with the Amazon DynamoDB OM is lazily loaded when possible, so calls to DynamoDB will be made only as needed. When you need to download all of the dataset in advance, you can call a size() method on the list to fetch the entire list.

Although the List returned in the low-level API is modifiable, the returned list in the Amazon DynamoDB OM is unmodifiable, and any attempts to modify the list will result in an exception. You may need to create a modifiable List object and move all of the data in order to use the result as a data source for a modifiable user interface component such as an editable ListActivity.

Scan is an expensive operation and should be used with care to avoid disrupting your higher priority production traffic on the table. See the Amazon DynamoDB Developer Guide for more recommendations for safely using the Scan operation.

Low-level API Amazon DynamoDB OM
ScanRequest request = new ScanRequest();
request.setTableName(PropertyLoader
			.getInstance()
			.getTestTableName());
ScanResult result = ddb.scan(request);

List> users = result.getItems();
		    
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
PaginatedScanList result = mapper.scan(
		UserPreference.class,
		scanExpression);

Retrieving a User's Preferences (Item Retrieval)

Knowing a user's userNo, the hash key of the table, it is easy to find the item for the user. This next snippet shows how to get all the attributes for an item using the hash key.

Low-level API Amazon DynamoDB OM
AttributeValue userNoAttr = new AttributeValue().withN(String
		.valueOf(userNo));
Key primaryKey = new Key().withHashKeyElement(userNoAttr);
GetItemRequest request = new GetItemRequest()
		.withTableName(PropertyLoader
				.getInstance()
				.getTestTableName())
		.withKey(primaryKey);

GetItemResult result = ddb.getItem(request);

Map userPreferences = result.getItem();
		    
UserPreference userPreference = mapper.load(UserPreference.class, userNo);

Modifying User Preferences (Item Update)

With the low-level API, a collection of attribute/value pairs are added to an update item request. With the DynamoDB Amazon DynamoDB OM, you update attributes on a UserPreference object, and then you can simply call the save method on the DynamoDB Mapper.

Low-level API Amazon DynamoDB OM
AttributeValue av = new AttributeValue().withS(value);
AttributeValueUpdate avu = new AttributeValueUpdate()
		.withValue(av)
		.withAction(AttributeAction.PUT);
Key primaryKey = new Key()
		.withHashKeyElement(targetValue);
HashMap updates =
		new HashMap();
updates.put(key, avu);

UpdateItemRequest request = new UpdateItemRequest()
		.withTableName(PropertyLoader
				.getInstance()
				.getTestTableName())
		.withKey(primaryKey)
		.withAttributeUpdates(updates);

ddb.updateItem(request);
updateUserPreference.setAutoLogin(isAutoLogin);
updateUserPreference.setVibrate(isVibrate);
updateUserPreference.setSilent(isSilent);
updateUserPreference.setColorTheme(colorTheme);

mapper.save(updateUserPreference);

Conclusion and Additional Resources

The code in this article demonstrates how to use the Amazon DynamoDB OM to perform various operations on items in Amazon DynamoDB tables. You can find more information about Amazon DynamoDB here.

A sample app that includes this code is hosted in our samples repository on GitHub:

The Amazon DynamoDB OM is supported for the Android platforms with API level 8 and higher (Android 2.2 and higher).

For more information about using Amazon DynamoDB OM, see the following article:

For recommendations about Amazon DynamoDB scan API, see the following FAQ:

For more information about using AWS credentials with mobile apps, see the following article:

Questions?

Please feel free to ask questions or provide comments in the Mobile Development Forum.

©2014, Amazon Web Services, Inc. or its affiliates. All rights reserved.