Explore DynamoDB annotations and learn how to load data from DynamoDB tables using the AWS SDK for Java Enhanced Client.
The AWS SDK for Java provides annotations that make it easier to map Java classes to DynamoDB tables. These annotations are part of the DynamoDB Enhanced Client, which provides a high-level, object-oriented interface for DynamoDB operations.
Here's an example of a Java POJO mapped to a DynamoDB table:
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute;
@DynamoDbBean
public class MusicItem {
private String artist;
private String songTitle;
private String albumTitle;
private int yearReleased;
private Set<String> genres;
@DynamoDbPartitionKey
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@DynamoDbSortKey
public String getSongTitle() {
return songTitle;
}
public void setSongTitle(String songTitle) {
this.songTitle = songTitle;
}
@DynamoDbAttribute("album_title") // Maps to different attribute name in DynamoDB
public String getAlbumTitle() {
return albumTitle;
}
// Other getters and setters...
}
Notes on the annotations:
@DynamoDbBean
@DynamoDbPartitionKey
@DynamoDbSortKey
@DynamoDbAttribute
with the DynamoDB nameThese annotations simplify working with DynamoDB by automatically handling the conversion between Java objects and DynamoDB items.
Once you've set up your annotated model classes, you can use the DynamoDB Enhanced Client to load data from your tables. The Enhanced Client provides several methods for retrieving data:
// Create the DynamoDB client
DynamoDbClient dynamoDbClient = DynamoDbClient.builder()
.region(Region.US_WEST_2)
.build();
// Create the enhanced client
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
.dynamoDbClient(dynamoDbClient)
.build();
// Create a table schema using the MusicItem class
DynamoDbTable<MusicItem> musicTable = enhancedClient.table("Music", TableSchema.fromBean(MusicItem.class));
To load a single item using its primary key:
// Create a key with partition key and sort key
Key key = Key.builder()
.partitionValue("Coldplay")
.sortValue("Viva La Vida")
.build();
// Get the item
MusicItem musicItem = musicTable.getItem(key);
if (musicItem != null) {
System.out.println("Found song: " + musicItem.getSongTitle() + " by " + musicItem.getArtist());
System.out.println("Album: " + musicItem.getAlbumTitle());
} else {
System.out.println("Song not found");
}
To retrieve multiple items matching a partition key:
// Query for all songs by an artist
QueryEnhancedRequest queryRequest = QueryEnhancedRequest.builder()
.queryConditional(QueryConditional.keyEqualTo(Key.builder()
.partitionValue("Coldplay")
.build()))
.build();
// Execute the query
PageIterable<MusicItem> pagedResults = musicTable.query(queryRequest);
// Process the results
for (MusicItem song : pagedResults.items()) {
System.out.println(song.getSongTitle() + " - " + song.getAlbumTitle());
}
You can refine queries with additional conditions:
// Query with sort key condition and filter
QueryEnhancedRequest queryWithFilter = QueryEnhancedRequest.builder()
.queryConditional(QueryConditional.sortBeginsWith(Key.builder()
.partitionValue("Coldplay")
.sortValue("V")
.build()))
.filterExpression(Expression.builder()
.expression("yearReleased > :year")
.expressionValues(Collections.singletonMap(":year", AttributeValue.builder().n("2007").build()))
.build())
.limit(10)
.build();
Remember that queries in DynamoDB always operate on a single partition key value, but can return multiple items with different sort keys. For cross-partition operations, you need to use a scan or global secondary indexes.
When working with DynamoDB and the Enhanced Client, keep these best practices in mind:
Robust error handling is crucial for DynamoDB operations:
try {
MusicItem result = musicTable.getItem(key);
// Process result
} catch (DynamoDbException e) {
System.err.println("Error getting item: " + e.getMessage());
// Handle specific exception types
if (e instanceof ResourceNotFoundException) {
// Table doesn't exist
} else if (e instanceof ProvisionedThroughputExceededException) {
// Implement retry with exponential backoff
}
}
Implementing these practices will help you build efficient, reliable applications that interact with DynamoDB.