dynobase-icon
Dynobase

DynamoDBMapper and Java Enhanced Client Cheat Sheet

Andrea Perera

Written by Andrea Perera

Last updated: October 23rd, 2026

Writing DynamoDB code by hand? Dynobase turns supported data operations into application code or scripts, and generates CDK, CloudFormation or Terraform for an existing table. Code generation in Dynobase

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.xEnhanced Client, SDK 2.x
com.amazonaws.services.dynamodbv2software.amazon.awssdk.services.dynamodb
DynamoDBMapperDynamoDbEnhancedClient 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

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?

DynamoDBMapper is the object-mapping API in AWS SDK for Java 1.x. It maps annotated Java beans to DynamoDB items and provides save, load, query, scan and batch methods. SDK 1.x reached end of support on December 31, 2025.

What replaces DynamoDBMapper in Java SDK 2.x?

Use DynamoDbEnhancedClient from the dynamodb-enhanced module. Map beans with TableSchema and perform single-table operations through DynamoDbTable.

Does DynamoDBMapper or the Enhanced Client require a sort key for Query?

No. Query requires equality on the partition key; a sort key is optional. If the table has a sort key, it can narrow and order the results, and both key attributes are required for Get and Delete.

Does the Java Enhanced Client paginate automatically?

Its Query, Scan and BatchGet iterables retrieve further pages as you iterate them. Keep the client open and consume all pages when you need all matches; a request limit is not the total result limit.

Does DynamoDbVersionAttribute protect deletes?

No. The default version extension protects supported put and update operations, but deletion needs an explicit version condition. Batch writes cannot enforce per-item version conditions.

Dynobase is a Professional GUI Client for DynamoDB

Start your 7-day free trial today

Product Features

Download
/
Pricing
/
Member Portal
/
Privacy
/
EULA
/
Twitter
© 2026 Dynobase