AWS SDK for Java でDynamoDBを操作する

build.gradle

plugins {
    id 'org.springframework.boot' version '2.5.0'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

dependencies {
    compileOnly 'org.projectlombok:lombok'
    implementation 'org.slf4j:slf4j-api'
    implementation 'ch.qos.logback:logback-core'
    implementation 'ch.qos.logback:logback-classic'
    implementation 'com.google.guava:guava:30.1.1-jre'
    implementation 'org.apache.commons:commons-lang3'
    implementation 'commons-beanutils:commons-beanutils:1.9.2'
    implementation 'com.amazonaws:aws-java-sdk-dynamodb:1.12.9'
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4'
    runtimeOnly 'mysql:mysql-connector-java' 
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

登録/取得/更新/検索のサンプル

package com.example.demo.dynamodb;

import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSCredentialsProviderChain;
import com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider;
import com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper;
import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemResult;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.PutItemResult;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class SampleDynamoDB {

    public static void main(String[] args) {
        final String token = putItem();
        getItem(token);
        update();
        search();
    }

    /**
    * 登録
    */
    private static String putItem() {
        final String token = UUID.randomUUID().toString();
        final Date now = new Date();
        // TTLを設定するフィールドは秒単位
        // https://aws.amazon.com/jp/premiumsupport/knowledge-center/ttl-dynamodb/
        final long expires = (now.getTime() / 1000) + (60 * 30); // 有効期間30分

        final Map<String, AttributeValue> item = new HashMap<>();
        item.put("authToken", new AttributeValue().withS(token));
        item.put("userId", new AttributeValue().withN("456"));
        item.put("createTime", new AttributeValue().withN(String.valueOf(now.getTime())));
        item.put("deleted", new AttributeValue().withBOOL(false));
        item.put("expires", new AttributeValue().withN(String.valueOf(expires)));

        final PutItemRequest putItemRequest = new PutItemRequest().withTableName("AuthTokenTable").withItem(item)
                .withReturnValues(ReturnValue.NONE);

        final AmazonDynamoDB dynamoDB = getDynamoDB();
        final PutItemResult result = dynamoDB.putItem(putItemRequest);
        System.out.println(result);

        return token;
    }

    /**
    * 取得
    */
    private static void getItem(String token) {
        final AmazonDynamoDB dynamoDB = getDynamoDB();
        final GetItemResult getItemResult = dynamoDB.getItem(new GetItemRequest().withTableName("AuthTokenTable")
                .withKey(Collections.singletonMap("authToken", new AttributeValue().withS(token)))
                .withConsistentRead(true));
        if (getItemResult.getItem() != null && !getItemResult.getItem().isEmpty()) {
            final Map<String, AttributeValue> item = getItemResult.getItem();
            final AttributeValue expires = item.get("expires");

            if (expires != null && expires.getN() != null && !expires.getN().isEmpty()) {
                final long l = Long.parseLong(expires.getN() + "000");
                final Date date = new Date(l);
                System.out.println(date);
            }
        }
    }

    /**
    * 更新
    */
    private static void update() {
        final String token = "a14c5498-349b-42a6-b737-3f512878ab80";
        final Date now = new Date();
        // TTLを設定するフィールドは秒単位
        // https://aws.amazon.com/jp/premiumsupport/knowledge-center/ttl-dynamodb/
        final long expires = (now.getTime() / 1000) + (60 * 30); // 有効期間30分

        final AmazonDynamoDB dynamoDB = getDynamoDB();
        final GetItemResult getItemResult = dynamoDB.getItem(new GetItemRequest().withTableName("AuthTokenTable")
                .withKey(Collections.singletonMap("authToken", new AttributeValue().withS(token)))
                .withConsistentRead(true));
        if (getItemResult.getItem() != null && !getItemResult.getItem().isEmpty()) {
            final Map<String, AttributeValue> item = getItemResult.getItem();

            // TTLを延長する場合
            item.put("expires", new AttributeValue().withN(String.valueOf(expires)));

            // 削除する場合
            item.put("deleted", new AttributeValue().withBOOL(true));

            final PutItemRequest putItemRequest = new PutItemRequest().withTableName("AuthTokenTable").withItem(item)
                    .withReturnValues(ReturnValue.NONE);
            final PutItemResult result = dynamoDB.putItem(putItemRequest);
            System.out.println(result);
        }
    }

    /**
    * 検索(GlobalSecondaryIndex)
    */
    private static void search() {
        final Long userId = 123L;

        final AmazonDynamoDB dynamoDB = getDynamoDB();
        final DynamoDB db = new DynamoDB(dynamoDB);
        Table table = db.getTable("AuthTokenTable");
        Index index = table.getIndex("UserIdIndex");

        QuerySpec spec = new QuerySpec().withKeyConditionExpression("userId = :userId")
                .withValueMap(new ValueMap().withLong(":userId", userId));
        ItemCollection<QueryOutcome> items = index.query(spec);

        Iterator<Item> iterator = items.iterator();
        while (iterator.hasNext()) {
            Item token = (Item) iterator.next();
            System.out.println(token);
        }
    }

    private static AmazonDynamoDB getDynamoDB() {
        final AWSCredentialsProvider providers = new AWSCredentialsProviderChain(
                new EnvironmentVariableCredentialsProvider(), new ClasspathPropertiesFileCredentialsProvider(),
                new ProfileCredentialsProvider(), new EC2ContainerCredentialsProviderWrapper());
        final String endpoint = "http://localhost:8000";
        final String region = "ap-northeast-1";
        final AmazonDynamoDBClientBuilder builder = AmazonDynamoDBClientBuilder.standard();
        builder.setCredentials(providers);
        builder.setEndpointConfiguration(new EndpointConfiguration(endpoint, region));
        return builder.build();
    }

}