ddb-spring-data-1
We will describe two ways for accessing DynamoDB from Spring applications:
- Using DynamoDB module of Spring Data
- Using Enhanced Client for DynamoDB which is part of AWS SDK 2.0.
DynamoDB Local Spring Data
Description
Using DynamoDB module of Spring Data
The Spring Data module for DynamoDB is a community module for accessing AWS DynamoDB with familiar Spring Data constructs of data objects and repository interfaces.
- JDK 17+
- Maven 3.8.5+ & Java 17
- Docker - for running LocalStack
Run Docker & DynamoDBLocal
Create table & items (e.g.)
{
"AttributeDefinitions": [
{
"AttributeName": "id",
"AttributeType": "N"
}
],
"TableName": "Music",
"KeySchema": [
{
"AttributeName": "id",
"KeyType": "HASH"
}
],
"TableStatus": "ACTIVE",
"CreationDateTime": "2024-09-15T09:36:39.613Z",
"ProvisionedThroughput": {
"LastIncreaseDateTime": "1970-01-01T00:00:00.000Z",
"LastDecreaseDateTime": "1970-01-01T00:00:00.000Z",
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 3,
"WriteCapacityUnits": 3
},
"TableSizeBytes": 95,
"ItemCount": 2,
"TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/Music",
"DeletionProtectionEnabled": false
}

Project Structure
.
├── pom.xml
├── README.md
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── jreact
│ │ └── dynamodb
│ │ ├── Application.java
│ │ ├── DynamoDbConfig.java
│ │ ├── MusicController.java
│ │ ├── MusicEntity.java
│ │ ├── MusicRepository.java
│ │ └── MusicService.java
│ └── resources
│ └── application.properties
└── test
└── java
└── com
└── jreact
└── dynamodb
└── MusicServiceTest.java
application.properties
dynamodb.endpoint=http://localhost:8000
region=us-east-1
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jreact</groupId>
<artifactId>ddb-spring-data-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ddb-spring-data-1</name>
<description>ddb-spring-data-1</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<lombok.version>1.18.34</lombok.version>
<aws.java.sdk.version>2.28.0</aws.java.sdk.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>${aws.java.sdk.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb-enhanced</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>DynamoDBLocal</artifactId>
<version>2.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>copy</id>
<phase>test-compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>test</includeScope>
<includeTypes>so,dll,dylib</includeTypes>
<outputDirectory>${project.build.directory}/native-libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin><!-- attach IT tests to verify phase -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<sqlite4java.library.path>${project.build.directory}/native-libs</sqlite4java.library.path>
</systemPropertyVariables>
<argLine>
--add-opens java.base/java.time=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<id>add-integration-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/integration-test/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-integration-test-resource</id>
<phase>generate-test-resources</phase>
<goals>
<goal>add-test-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/integration-test/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
DynamoDbConfig.java
package com.jreact.dynamodb;
import java.net.URI;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.extensions.VersionedRecordExtension;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
@Configuration
@NoArgsConstructor
@Slf4j
public class DynamoDbConfig {
@Value("${dynamodb.endpoint:}")
private String dynamodbEndpoint;
@Value("${region:}")
private String region;
@Bean
public DynamoDbClient getDynamoDbClient() {
var builder = DynamoDbClient
.builder()
.credentialsProvider(DefaultCredentialsProvider.create());
if (dynamodbEndpoint != null && !dynamodbEndpoint.isBlank()) {
builder.region(Region.of(region))
.endpointOverride(URI.create(dynamodbEndpoint));
log.info("ddb region: " + region);
log.info("ddb endpoint: " + dynamodbEndpoint);
}
return builder.build();
}
@Bean
public DynamoDbEnhancedClient getDynamoDbEnhancedClient(DynamoDbClient ddbc) {
return DynamoDbEnhancedClient
.builder()
.extensions(VersionedRecordExtension.builder().build())
.dynamoDbClient(ddbc)
.build();
}
@Bean
public DynamoDbTable<MusicEntity> getMusicLocaleTable(DynamoDbEnhancedClient dbClient) {
return dbClient.table(MusicEntity.TABLE_NAME, TableSchema.fromBean(MusicEntity.class));
}
}
MusicEntity.java
package com.jreact.dynamodb;
import lombok.Data;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
@DynamoDbBean
@Data
public class MusicEntity {
public static final String TABLE_NAME = "Music";
private String musicCode;
private String musicDisplayName;
@DynamoDbPartitionKey
public String getMusicCode() {
return musicCode;
}
}
Running and Testing
mvn clean package
mvn spring-boot:run
Output (Browser):

Source Code
https://github.com/ZbCiok/zjc-examples/tree/main/aws/aws/dynamodb/ddb-spring-data-1
📄️ ddb-create-table-example-01
Description
📄️ ddb-write-read-example-01
Description
📄️ ddb-delete-table-example-01
Description
📄️ ddb-enh-client-spring-boot-1
We will describe two ways for accessing DynamoDB from Spring applications:
📄️ ddb-spring-data-1
We will describe two ways for accessing DynamoDB from Spring applications:
📄️ Spring Boot SNS Lambda DynamoDB
Description