DynamoDBMapper and Java Enhanced Client Cheat Sheet

Written by Andrea Perera
Last updated: October 23rd, 2026
DynamoDBMapper maps Java objects to DynamoDB items in AWS SDK for Java 1.x, which reached end of support on December 31, 2025. For current applications, use the AWS SDK for Java 2.x DynamoDB Enhanced Client: annotate a bean, create a TableSchema, and call methods on a DynamoDbTable. The examples below cover the same CRUD, query, scan and batch operations, followed by transactions, optimistic locking and a legacy Mapper reference.
DynamoDBMapper to Enhanced Client mapping
The Enhanced Client is AWS's successor to DynamoDBMapper. Migration changes imports, annotations, request builders and some persistence behavior; replacing the dependency alone is insufficient.
| DynamoDBMapper, SDK 1.x | Enhanced Client, SDK 2.x |
|---|---|
com.amazonaws.services.dynamodbv2 | software.amazon.awssdk.services.dynamodb |
DynamoDBMapper | DynamoDbEnhancedClient plus DynamoDbTable |
@DynamoDBTable(tableName = "Product") | @DynamoDbBean and enhanced.table("Product", schema) |
@DynamoDBHashKey | @DynamoDbPartitionKey |
@DynamoDBRangeKey | @DynamoDbSortKey |
@DynamoDBAttribute(attributeName = "Price") | @DynamoDbAttribute("Price") |
mapper.save(item) | Explicit table.putItem(item) or table.updateItem(item) |
mapper.load(Product.class, id, name) | table.getItem(Key.builder().partitionValue(id).sortValue(name).build()) |
mapper.query(...) / mapper.scan(...) | table.query(...) / table.scan(...) with paginated iterables |
mapper.batchSave(...) / mapper.batchDelete(...) | enhanced.batchWriteItem(...), then retry unprocessed writes |
mapper.batchLoad(...) | Iterate enhanced.batchGetItem(...) |
mapper.transactionWrite(...) / transactionLoad(...) | enhanced.transactWriteItems(...) / transactGetItems(...) |
@DynamoDBVersionAttribute | @DynamoDbVersionAttribute and VersionedRecordExtension |
Keep existing attribute names and key types during migration. Table names move out of bean annotations and into client configuration. Review the AWS mapping API comparison before translating custom converters or save behaviors.
Cheat-sheet contents
- Setup
- Create a model class
- Connection
- Create a table
- Put an item
- Get an item
- Update an item
- Batch put items
- Batch put and delete
- Batch get items
- Scan with a filter
- Parallel scan
- Query
- Delete an item
- Batch delete items
- Transactions
- Optimistic locking
- Delete a table
- DynamoDB Local
- Legacy DynamoDBMapper
Setup
These examples use Java 17 or later and AWS SDK for Java 2.x. Java 17 is the example baseline, not the minimum for every SDK 2.x release. Use the SDK BOM to align module versions. For a Gradle project, the dependency block is:
The SSO modules support IAM Identity Center profiles during local development. Configure a Region and credentials through an AWS profile or runtime IAM role. Grant the table operations your application needs; static access keys and an administrator policy are not prerequisites. Spring Boot is optional: the SDK works in an ordinary Java application.
Save the bean below as Product.java. The operation snippets are method-body excerpts: use the imports and ProductExamples scaffold in the connection section, and run each example separately against a disposable table. They are not an ordered script, because the deletion examples remove data used elsewhere.
Create a model class and table schema
The Product table has Number partition key ProductId and String sort key ProductName. Every item lookup needs both. Price and weight use BigDecimal; names in annotations preserve the stored attribute names independently of Java property casing.
The bean needs a public no-argument constructor and getters/setters. TableSchema.fromBean(Product.class) inspects its annotations. Reuse the schema instead of rebuilding it per request. The version property is initially ordinary data; the locking section shows the annotation that changes its behavior.
Do not use a String UUID generator on an Integer key. If an existing table has String ProductId values, change the Java property and the example key values to String rather than changing the existing table's schema.
Connect and map the table
Use these imports for the operation snippets. Add an operation inside main; add the batch helper shown later as another static method in this class.
Creating the mapped table handle does not create a remote table. Keep the low-level client open while iterating results because lazy pagination makes additional requests. In a server application, reuse clients and close them at application shutdown.
Create a table
The low-level client makes the exact key types and on-demand billing explicit. Attribute definitions contain only keys, not Price, Weight or version.
Wait for the table to become active before writing. A table with only a partition key can also be queried, but this example intentionally has a sort key so multiple items can share a ProductId.
Put an item
Put replaces an entire existing item. Use a condition for a create-only write so an accidental duplicate cannot erase attributes omitted from your bean.
This condition applies to the full key, including ProductName. It does not require the entire partition to be empty. Catch ConditionalCheckFailedException if the same key already exists.
Get an item
A Get requires both key attributes. It returns null when the item does not exist. A strongly consistent base-table read observes completed writes in that Region.
Get does not search by price or fetch every item sharing the partition key. Use Query for the latter and design a secondary index for other access patterns.
Update an item and handle nulls
Enhanced Client updateItem removes mapped attributes whose bean properties are null by default. For a patch to scalar fields, use IgnoreNullsMode.SCALAR_ONLY and an existence condition. This preserves the stored weight when the patch does not set it.
Alternatively, get the item first, check for null, change its price and weight, then call updateItem. That read-modify-write sequence needs optimistic locking to detect concurrent changes. Do not assume a type-safe bean makes concurrent writes safe. For raw update expressions, see the SDK 2.x update example.
Batch put items with bounded retries
A batch writes at most 25 puts/deletes and a 16 MB request. It does not update selected attributes, support conditions or execute atomically. Use this helper for the unversioned Product bean above; retry only unfinished operations and retain them if retries run out.
Add this exception type and method to ProductExamples, outside main. The exception exposes pending work so the caller can save it for a later retry:
Call it with distinct complete keys. Each put replaces any existing item at its key:
Check item and wire sizes when constructing real batches; the operation count alone does not guarantee they fit. Batches are unsuitable for writes that require version or state conditions. See the Enhanced Client batch API.
Batch put and delete
Puts and deletes can share one batch, provided they target different items. This keeps the same schema and retry helper rather than introducing undefined purchase or category models.
To target multiple tables, add a WriteBatch for each mapped table to the same request and retain each table's unprocessed results. The 25-operation limit applies across the entire request, not separately to each table.
Batch get items
BatchGet reads known keys, up to 100 items and 16 MB per service response. Iterate the Enhanced Client's result iterable: it requests further pages and retries unprocessed keys. Results can be unordered, and nonexistent items are omitted.
Keep keys unique and split inputs above the request limit. If you need strongly consistent reads, set consistentRead(true) on every GetItemEnhancedRequest for that table. BatchGet is not an atomic read transaction.
Scan with a filter
The items() iterable walks all pages without collecting the table into memory. A filter is applied after DynamoDB reads each page, so it does not lower read capacity. Unlike a Query filter, a Scan filter may refer to key attributes.
Each service response evaluates up to 1 MB before filtering. An empty page can still have a continuation key. Lazy iteration handles that, but scans are not snapshots and can see concurrent changes.
Parallel scan
Use a separate worker for each segment. Every worker must keep its segment number and total segment count while reading all pages. Parallelism can shorten elapsed time while consuming capacity faster; it does not make a full scan cheaper.
The example waits for worker results so exceptions are not silently lost. Production jobs should checkpoint each segment separately and set request timeouts. DynamoDB Local does not reproduce parallel scan segmentation, so test that behavior against AWS.
Query a partition and paginate results
Query requires partition-key equality. A sort key is optional in DynamoDB generally; when present, it supports additional predicates and orders the results. Here, query every item whose ProductId is 1, in descending ProductName order.
limit(100) limits evaluated items per request, not the total number of results from the iterable. To narrow the sort key, use a condition such as QueryConditional.sortBeginsWith(Key.builder().partitionValue(1).sortValue("Product").build()). Non-key filters run after the key condition and do not reduce the data read.
For an index query, map its key properties with @DynamoDbSecondaryPartitionKey and @DynamoDbSecondarySortKey, obtain table.index("IndexName"), and query using its keys. GSIs provide eventually consistent reads only. The Java index example shows the equivalent low-level SDK 2.x request.
Delete one item
Delete takes the full key and returns the previous item, or null if none existed. A plain key-based deletion does not need a preliminary read.
If deletion depends on an expected version or state, use DeleteItemEnhancedRequest with an explicit condition. Merely passing a bean with a version property does not add that condition automatically.
Batch delete items
Reuse the bounded batch helper with no puts. There is no need to load complete records when the full keys are already known.
Use individual conditional deletes or a transaction if a version must still match. For table-wide cleanup, delete all items with Java scans keys and handles pagination and batch retries.
Write and read transactions
Transactions coordinate changes atomically across up to 100 distinct items and 4 MB in one account and Region. They cannot target the same item twice or operate on MRSC global tables. This writes two new products with create-only conditions.
Use one unique token per logical transaction and reuse the identical payload and token for retries within the 10-minute idempotency window. Catch TransactionCanceledException and inspect cancellationReasons(); a failed condition is not fixed by blindly retrying.
Read both items atomically with transactGetItems. Result documents preserve request order, and getItem(table) returns null for a missing item:
The Enhanced Client transaction guide covers combining puts, updates, deletes and condition checks.
Optimistic locking with DynamoDbVersionAttribute
For records updated concurrently, replace the existing getVersion() method in Product with this annotated version. Add the import at the top of Product.java; keep the existing field and setter. This is a model change, so recreate the schema/client after recompiling.
VersionedRecordExtension is loaded by default. It initializes a new version at 0 and increments it on successful writes, adding a version condition. Explicitly configuring your own extension list replaces the defaults, so include VersionedRecordExtension there when needed.
Read the item, modify it and keep the returned updated object for subsequent writes:
The earlier scalar patch example must now carry the version read from the item. A null version means a new, unversioned item to the extension, not permission to overwrite an existing version. Avoid batch writes for version-controlled records because BatchWriteItem cannot enforce per-item conditions.
Version annotations do not protect deletes. Read the version and add the condition yourself:
Multi-Region eventual consistency global tables use last-writer-wins reconciliation, so a local version condition is not a cross-Region lock. The extension reference describes which operations apply version checks.
Delete a table
This deletes the table and all its data. Run it only after the disposable examples are finished. Deletion protection must be disabled.
A successful not-exists waiter is matched by a ResourceNotFoundException, not a DescribeTable response. Check the matched exception when confirming deletion:
Run DynamoDB Local
Use the current DynamoDB Local 3.x image. Running the downloaded JAR directly requires JRE 17 or later; the Docker image supplies its runtime. This disposable example stores data only in memory.
In the connection scaffold, replace the client construction with this local configuration. Keep the rest of the Enhanced Client setup the same, and create the table at this endpoint first.
Dummy credentials are for Local only. Local does not model real throughput throttling or every cloud feature. The local development guide covers persistent storage and other clients.
DynamoDBMapper for existing SDK 1.x code
Keep this section only as a migration reference. The legacy package is com.amazonaws:aws-java-sdk-dynamodb; it is not part of SDK 2.x. A correctly mapped composite-key bean uses @DynamoDBHashKey and @DynamoDBRangeKey, and load needs both values.
In an existing 1.x project, read it using the default credentials chain:
Legacy save behavior depends on DynamoDBMapperConfig.SaveBehavior, so translate the intended overwrite, patch and null-handling behavior explicitly. Map all attributes needed by your application before writing; the small legacy bean here is read-only. Existing batch methods also require checking their returned failures. The Mapper method reference remains useful while migrating.
Frequently asked questions
Frequently Asked Questions
What is DynamoDBMapper?
What replaces DynamoDBMapper in Java SDK 2.x?
Does DynamoDBMapper or the Enhanced Client require a sort key for Query?
Does the Java Enhanced Client paginate automatically?
Does DynamoDbVersionAttribute protect deletes?
Dynobase is a Professional GUI Client for DynamoDB
Start your 7-day free trial today