Menu
AWS Mobile
Developer Guide

Add NoSQL Database to Your Mobile App with Amazon DynamoDB

Overview

The AWS Mobile Hub nosqldb feature uses Amazon DynamoDB to enable you to create database tables that can store and retrieve data for use by your apps.

Set Up Your Backend

  1. Complete the Get Started steps before you proceed.

  2. Enable NoSQL Database: Open your project in Mobile Hub and choose the NoSQL Database tile to enable the feature.

  3. Follow the console work flow to define the tables you need. See Configuring the NoSQL Database Feature for details.

  4. When the operation is complete, an alert will pop up saying "Your Backend has been updated", prompting you to download the latest copy of the cloud configuration file. If you're done configuring the feature, choose the banner to return to the project details page.

  5. From the project detail page, every app that needs to be updated with the latest cloud configuration file will have a flashing Integrate button. Choose the button to enter the integrate wizard.

  6. Update your app with the latest copy of the cloud configuration file. Your app now references the latest version of your backend. Choose Next and follow the NoSQL Database documentation below to connect to your backend.

  7. Download the models required for your app. The data models provide set and get methods for each attribute of a DynamoDB table.

Connect to your backend

To add AWS Mobile NoSQL Database to your app

Android - JavaAndroid - KotliniOS - Swift
Android - Java
  1. Set up AWS Mobile SDK components with the following Set Up Your Backend steps.

    1. app/build.gradle must contain:

      dependencies{ implementation 'com.amazonaws:aws-android-sdk-ddb-mapper:2.6.+' }
    2. For each Activity where you make calls to perform database operations, import the following APIs.

      import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper;
  2. Create a DynamoDBMapper client for your app as in the following example.

    import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.mobile.client.AWSMobileClient; import com.amazonaws.mobile.config.AWSConfiguration; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import java.util.Random; public class MainActivity extends AppCompatActivity { // Declare a DynamoDBMapper object DynamoDBMapper dynamoDBMapper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // AWSMobileClient enables AWS user credentials to access your table AWSMobileClient.getInstance().initialize(this).execute(); AWSCredentialsProvider credentialsProvider = AWSMobileClient.getInstance().getCredentialsProvider(); AWSConfiguration configuration = AWSMobileClient.getInstance().getConfiguration(); // Add code to instantiate a AmazonDynamoDBClient AmazonDynamoDBClient dynamoDBClient = new AmazonDynamoDBClient(credentialsProvider); this.dynamoDBMapper = DynamoDBMapper.builder() .dynamoDBClient(dynamoDBClient) .awsConfiguration(configuration) .build(); // other activity code ... } }
  3. Add the project data model files you downloaded from the Mobile Hub console. The data models provide set and get methods for each attribute of a DynamoDB table they model.

    1. Copy the data model file(s) you downloaded, ./YOUR-PROJECT-NAME-integration-lib-aws-my-sample-app-android/src/main/java/com/amazonaws/models/nosqlYOUR-TABLE-NAMEDO.java into the Android Studio folder that contains your main activity.

Note

Use Asynchronous Calls to DynamoDB

Since calls to DynamoDB are synchronous, they don't belong on your UI thread. Use an asynchronous method like the Runnable wrapper to call DynamoDBObjectMapper in a separate thread.

Runnable runnable = new Runnable() { public void run() { //DynamoDB calls go here } }; Thread mythread = new Thread(runnable); mythread.start();
Android - Kotlin
  1. Set up AWS Mobile SDK components with the following Set Up Your Backend steps.

    1. app/build.gradle must contain:

      dependencies{ implementation 'com.amazonaws:aws-android-sdk-ddb-mapper:2.6.+' }
    2. For each Activity where you make calls to perform database operations, import the following APIs.

      import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper;
  2. Create a DynamoDBMapper client for your app as in the following example.

    // import DynamoDBMapper import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper; class MainActivity : AppCompatActivity() { private var dynamoDBMapper: DynamoDBMapper? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val client = AmazonDynamoDBClient(AWSMobileClient.getInstance().credentialsProvider) dynamoDBMapper = DynamoDBMapper.builder() .dynamoDBClient(client) .awsConfiguration(AWSMobileClient.getInstance().configuration) .build() } }
  3. Add the project data model files you downloaded from the Mobile Hub console. The data models provide set and get methods for each attribute of a DynamoDB table they model.

    1. Copy the data model file(s) you downloaded, ./YOUR-PROJECT-NAME-integration-lib-aws-my-sample-app-android/src/main/java/com/amazonaws/models/nosqlYOUR-TABLE-NAMEDO.java into the Android Studio folder that contains your main activity.

Note

Use Asynchronous Calls to DynamoDB

Since calls to DynamoDB are synchronous, they don't belong on your UI thread. Use an asynchronous method like the thread wrapper to call DynamoDBObjectMapper in a separate thread.

thread(start = true) { // DynamoDB calls go here }
iOS - Swift
  1. Set up AWS Mobile SDK components with the following Set Up Your Backend steps.

    1. Podfile that you configure to install the AWS Mobile SDK must contain:

      platform :ios, '9.0' target :'YOUR-APP-NAME' do use_frameworks! pod 'AWSDynamoDB', '~> 2.6.13' # other pods end

      Run pod install --repo-update before you continue.

      If you encounter an error message that begins "[!] Failed to connect to GitHub to update the CocoaPods/Specs . . .", and your internet connectivity is working, you may need to update openssl and Ruby.

    2. Classes that call DynamoDB APIs must use the following import statements:

      import AWSCore import AWSDynamoDB
  2. From the location where you downloaded the data model file(s), drag and drop each file with the form of your-table-name.swift into the folder that contains your AppDelegate.swift. Select Copy items if needed and Create groups, if these options are offered.

Perform CRUD Operations

Using the Data Model

To connect your app to an Amazon DynamoDB table you have created, use a data model generated by Mobile Hub, or create one in the following form. As an example, the fragments in the following sections are based on a table named News. The table's partition key (hash key) is named userID, the sort key (range key) is called articleId and other attributes, including author, title, category, content, and content.

Android - JavaAndroid - KotliniOS - Swift
Android - Java

In the following example, the NewsDO class defines the data model of the News table. The class is used by the CRUD methods in this section to access the table and its attributes. The data model file you downloaded from Mobile Hub in previous steps contains a similar class that defines the model of your table.

Note that the class is annotated to map it to the Amazon DynamoDB table name. The attribute names, hash key, and range key of the getters in the class are annotated to map them to local variable names used by the app for performing data operations.

package com.amazonaws.models.nosql; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBAttribute; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBHashKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBIndexHashKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBIndexRangeKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBRangeKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBTable; import java.util.List; import java.util.Map; import java.util.Set; @DynamoDBTable(tableName = "nosqlnews-mobilehub-1234567890-News") public class NewsDO { private String _userId; private String _articleId; private String _author; private String _category; private String _content; private Double _creationDate; private String _title; @DynamoDBHashKey(attributeName = "userId") @DynamoDBAttribute(attributeName = "userId") public String getUserId() { return _userId; } public void setUserId(final String _userId) { this._userId = _userId; } @DynamoDBRangeKey(attributeName = "articleId") @DynamoDBAttribute(attributeName = "articleId") public String getArticleId() { return _articleId; } public void setArticleId(final String _articleId) { this._articleId = _articleId; } @DynamoDBAttribute(attributeName = "author") public String getAuthor() { return _author; } public void setAuthor(final String _author) { this._author = _author; } // setters and getters for other attribues ... }
Android - Kotlin

In the following example, the NewsDO class defines the data model of the News table. The class is used by the CRUD methods in this section to access the table and its attributes. The data model file you downloaded from Mobile Hub in previous steps contains a similar class that defines the model of your table.

Note that the class is annotated to map it to the Amazon DynamoDB table name. The attribute names, hash key, and range key of the getters in the class are annotated to map them to local variable names used by the app for performing data operations.

package com.amazonaws.models.nosql; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBAttribute; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBHashKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBIndexHashKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBIndexRangeKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBRangeKey; import com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBTable; import java.util.List; import java.util.Map; import java.util.Set; @DynamoDBTable(tableName = "nosqlnews-mobilehub-1234567890-News") data class NewsDO { @DynamoDBHashKey(attributeName = "userId" ) @DynamoDBAttribute(attributeName = "userId") var userId: String? @DynamoDBRangeKey(attributeName = "articleId") @DynamoDBAttribute(attributeName = "articleId") var articleId: String? @DynamoDBAttribute(attributeName = "author") var author: String? // setters and getters for other attribues ... }

If you download an Android model file generated by Mobile Hub, it will be provided in Java and can be used in a Kotlin project without modifications.

iOS - Swift

In the following example, the News class defines the data model of the News table. The class is used by the CRUD methods in this section to access the table and its attributes. The data model file you downloaded from Mobile Hub in previous steps contains a similar class that defines the model of your table.

Note that the functions of the model class return the Amazon DynamoDB table, hash key attibute, and range key attribute names used by the app for data operations. For example, dynamoDBTableName() returns the name of the table object in AWS. The local variable names map to the attribute names of the table. For instance, userId is the name of both the local variable and the attribute of the Amazon DynamoDB table.

This example is slightly simpler than the data model generated by Mobile Hub, but functionally the same.

// News.swift import Foundation import UIKit import AWSDynamoDB class News: AWSDynamoDBObjectModel, AWSDynamoDBModeling { @objc var userId: String? @objc var articleId: String? @objc var author: String? @objc var category: String? @objc var content: String? @objc var creationDate: NSNumber? @objc var title: String? class func dynamoDBTableName() -> String { return "nosqlnews-mobilehub-1200412570-News" } class func hashKeyAttribute() -> String { return "userId" } class func rangeKeyAttribute() -> String { return "articleId" } }

Create (Save) an Item

Use the following code to create an item in your NoSQL Database table.

Android - JavaAndroid - KotliniOS - Swift
Android - Java
public void createNews() { final NewsDO newsItem = new NewsDO(); newsItem.setUserId(unique-user-id); newsItem.setArticleId("Article1"); newsItem.setContent("This is the article content"); new Thread(new Runnable() { @Override public void run() { dynamoDBMapper.save(newsItem); // Item saved } }).start(); }
Android - Kotlin
fun createNews() { val NewsDO newsItem = NewsDO() newsItem.userId = "unique-user-id" newsItem.articleId = UUID.randomUUID().toString() newsItem.author = "Your Name" newsItem.content = "This is the article content" thread(start = true) { dynamoDBMapper.save(newsItem) } }
iOS - Swift
func createNews() { let dynamoDbObjectMapper = AWSDynamoDBObjectMapper.default() // Create data object using data models you downloaded from Mobile Hub let newsItem: News = News() newsItem.userId = AWSIdentityManager.default().identityId newsItem.articleId = "YourArticleId" newsItem.title = "YourTitlestring" newsItem.author = "YourAuthor" newsItem.creationDate = NSDate().timeIntervalSince1970 as NSNumber //Save a new item dynamoDbObjectMapper.save(newsItem, completionHandler: { (error: Error?) -> Void in if let error = error { print("Amazon DynamoDB Save Error: \(error)") return } print("An item was saved.") }) }

Read (Load) an Item

Use the following code to read an item in your NoSQL Database table.

Android - JavaAndroid - KotliniOS - Swift
Android - Java
public void readNews() { new Thread(new Runnable() { @Override public void run() { NewsDO newsItem = dynamoDBMapper.load( NewsDO.class, unique-user-id, "Article1"); // Item read // Log.d("News Item:", newsItem.toString()); } }).start(); }
Android - Kotlin
fun readNews(userId: String, articleId: String, callback: (NewsDO?) -> Unit) { thread(start = true) { var newsItem = dynamoDBMapper.load(NewsDO::class.java, userId, articleId) runOnUiThread { callback(newsItem) } } }
iOS - Swift
func readNews() { let dynamoDbObjectMapper = AWSDynamoDBObjectMapper.default() // Create data object using data models you downloaded from Mobile Hub let newsItem: News = News(); newsItem.userId = AWSIdentityManager.default().identityId dynamoDbObjectMapper.load( News.self, hashKey: newsItem.userId, rangeKey: "YourArticleId", completionHandler: { (objectModel: AWSDynamoDBObjectModel?, error: Error?) -> Void in if let error = error { print("Amazon DynamoDB Read Error: \(error)") return } print("An item was read.") }) }

Update an Item

Use the following code to update an item in your NoSQL Database table.

Android - JavaAndroid - KotliniOS - Swift
Android - Java
public void updateNews() { final NewsDO newsItem = new NewsDO(); newsItem.setUserId(unique-user-id); newsItem.setArticleId("Article1"); newsItem.setContent("This is the updated content."); new Thread(new Runnable() { @Override public void run() { dynamoDBMapper.save(newsItem); // Item updated } }).start(); }
Android - Kotlin
fun updateNews(updatedNews: NewsDO) { thread(start = true) { dynamoDBMapper.save(updatedNews) } }
iOS - Swift
func updateNews() { let dynamoDbObjectMapper = AWSDynamoDBObjectMapper.default() let newsItem: News = News(); newsItem.userId = "unique-user-id" newsItem.articleId = "YourArticleId" newsItem.title = "This is the Title" newsItem.author = "B Smith" newsItem.creationDate = NSDate().timeIntervalSince1970 as NSNumber newsItem.category = "Local News" dynamoDbObjectMapper.save(newsItem, completionHandler: {(error: Error?) -> Void in if let error = error { print(" Amazon DynamoDB Save Error: \(error)") return } print("An item was updated.") }) }

Delete an Item

Use the following code to delete an item in your NoSQL Database table.

Android - JavaAndroid - KotliniOS - Swift
Android - Java
public void deleteNews() { new Thread(new Runnable() { @Override public void run() { NewsDO newsItem = new NewsDO(); newsItem.setUserId(unique-user-id); //partition key newsItem.setArticleId("Article1"); //range (sort) key dynamoDBMapper.delete(newsItem); // Item deleted } }).start(); }
Android - Kotlin
public void deleteNews(userId: String, articleId: String) { thread(start = true) { val item = NewsDO() item.userId = userId item.articleId = articleId dynamoDBMapper.delete(item) } }
iOS - Swift
func deleteNews() { let dynamoDbObjectMapper = AWSDynamoDBObjectMapper.default() let itemToDelete = News() itemToDelete?.userId = "unique-user-id" itemToDelete?.articleId = "YourArticleId" dynamoDbObjectMapper.remove(itemToDelete!, completionHandler: {(error: Error?) -> Void in if let error = error { print(" Amazon DynamoDB Save Error: \(error)") return } print("An item was deleted.") }) }

Perform a Query

A query operation enables you to find items in a table. You must define a query using both the hash key (partition key) and range key (sort key) attributes of a table. You can filter the results by specifying the attributes you are looking for.

The following example code shows querying for news submitted with userId (hash key) and article ID beginning with Trial (range key).

Android - JavaAndroid - KotliniOS - Swift
Android - Java
public void queryNews() { new Thread(new Runnable() { @Override public void run() { NewsDO news = new NewsDO(); news.setUserId(unique-user-id); news.setArticleId("Article1"); Condition rangeKeyCondition = new Condition() .withComparisonOperator(ComparisonOperator.BEGINS_WITH) .withAttributeValueList(new AttributeValue().withS("Trial")); DynamoDBQueryExpression queryExpression = new DynamoDBQueryExpression() .withHashKeyValues(note) .withRangeKeyCondition("articleId", rangeKeyCondition) .withConsistentRead(false); PaginatedList<NewsDO> result = dynamoDBMapper.query(NewsDO.class, queryExpression); Gson gson = new Gson(); StringBuilder stringBuilder = new StringBuilder(); // Loop through query results for (int i = 0; i < result.size(); i++) { String jsonFormOfItem = gson.toJson(result.get(i)); stringBuilder.append(jsonFormOfItem + "\n\n"); } // Add your code here to deal with the data result Log.d("Query result: ", stringBuilder.toString()); if (result.isEmpty()) { // There were no items matching your query. } } }).start(); }
Android - Kotlin
public void queryNews(userId: String, articleId: String, callback: (List<NewsDO>?) -> Unit) { thread(start = true) { val item = NewsDO() item.userId = userId item.articleId = articleId val rangeKeyCondition = Condition() .withComparisonOperator(ComparisonOperator.BEGINS_WITH) .withAttributeValueList(AttributeValue().withS("Trial")) val queryExpression = DynamoDBQueryExpression() .withHashKeyValues(item) .withRangeKeyCondition("articleId", rangeKeyCondition) .withConsistentRead(false); val result = dynamoDBMapper.query(NewsDO::class.java, queryExpression) runOnUiThread { callback(result) } } }
iOS - Swift
func queryNote() { // 1) Configure the query let queryExpression = AWSDynamoDBQueryExpression() queryExpression.keyConditionExpression = "#articleId >= :articleId AND #userId = :userId" queryExpression.expressionAttributeNames = [ "#userId": "userId", "#articleId": "articleId" ] queryExpression.expressionAttributeValues = [ ":articleId": "SomeArticleId", ":userId": "unique-user-id" ] // 2) Make the query let dynamoDbObjectMapper = AWSDynamoDBObjectMapper.default() dynamoDbObjectMapper.query(News.self, expression: queryExpression) { (output: AWSDynamoDBPaginatedOutput?, error: Error?) in if error != nil { print("The request failed. Error: \(String(describing: error))") } if output != nil { for news in output!.items { let newsItem = news as? News print("\(newsItem!.title!)") } } } }