AWSメモ >

AWS Java SDKでDynamoDBのCRUDを書いてみる

AWS Java SDK の DynamoDB関連パッケージ

以下の com.amazonaws.services.dynamodbv2 が DynamoDB関連パッケージ。
https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html

Java SDK利用時の注意点

例えば、同じデータ登録を行う場合でも、様々なインターフェースが用意されている為、要件に応じて使い分ける必要がある。
例として、レコードを登録するインターフェースを挙げるが、ざっと見渡しただけで、これだけのインターフェースがある。

com.amazonaws.services.dynamodbv2.AmazonDynamoDB

戻り値メソッド
PutItemResultputItem(PutItemRequest request)
PutItemResultputItem(String tableName, Map<String,AttributeValue> item)
PutItemResultputItem(String tableName, Map<String,AttributeValue> item, String returnValues)

com.amazonaws.services.dynamodbv2.document.Table

戻り値メソッド
PutItemOutcomeputItem(Item item)
PutItemOutcomeputItem(Item item, Expected... expected)
PutItemOutcomeputItem(Item item, String conditionExpression, Map<String,String> nameMap, Map<String,Object> valueMap)
PutItemOutcomeputItem(PutItemSpec spec)

※さらにバッチWrite 等は com.amazonaws.services.dynamodbv2.document.DynamoDB で提供されている。

個人的には、

AmazonDynamoDB.putItem(PutItemRequest request)、AmazonDynamoDB.updateItem(UpdateItemRequest request) 等の XxxxItemRequest 系を引数にとるメソッドか、

Table.putItem(PutItemSpec spec)、Table.updateItem(UpdateItemSpec spec) 等の XxxxItemSpec 系を引数にとるメソッドを使用しておけば大抵のケースには対応できる気はしている。

逆に、putItem(Item item) などを使用していると、登録結果のデータを戻り値で取得したいケースや、消費したキャパシティユニットを戻り値で得たいケースには対応できない。

※XxxxItemRequest とか XxxxItemSpec だと withReturnValues や withReturnConsumedCapacity で登録/更新結果や、キャパシティユニットも返却できるようになるので。

DynamoDBMapperについて

Java版のSDKでは、DynamoDBMapper といういわゆるO/Rマッピングツールが提供されている。
ただし、なぜかデフォルトでMap型がサポートされていない。
※恐らく DynamoDBTypeConverted アノテーションを利用して、自力でコンバーターを作ればマッピング可能と思われる。

テスト用プロジェクトの作成

https://docs.aws.amazon.com/ja_jp/sdk-for-java/v1/developer-guide/setup-project-maven.html

mkdir aws-sdk-java-test && cd aws-sdk-java-test
gradle init --type java-application
rm -rf src/main/java/*
rm -rf src/test/java/*

build.gradle の編集

plugins {
    id 'java'
    id 'application'
}

mainClassName = 'ScanTable'

dependencies {
    compile 'com.google.guava:guava:23.0'
    //compile 'com.amazonaws:aws-java-sdk:latest.release'
    compile 'com.amazonaws:aws-java-sdk-dynamodb:latest.release'
    compile 'com.google.code.gson:gson:2.8.2'
    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0'

    testCompile 'junit:junit:4.12'
}

repositories {
    jcenter()
}

run {
    // 引数で指定されたクラスを実行する
    if (project.hasProperty('main')) {    
        main(project.main)
    }   
}

テーブルの作成

DDL格納用フォルダ作成

mkdir -p  src/test/resources/ddl

テーブル定義の作成

src/test/resources/ddl/SampleTable.json

{
    "TableName": "SampleTable",
    "AttributeDefinitions": [
        { "AttributeName": "pkey", "AttributeType": "S" },
        { "AttributeName": "skey", "AttributeType": "S" }
    ],  
    "KeySchema": [
        { "AttributeName": "pkey", "KeyType": "HASH" },
        { "AttributeName": "skey", "KeyType": "RANGE" }
    ],  
    "ProvisionedThroughput": { "WriteCapacityUnits": 1, "ReadCapacityUnits": 1 } 
}

テーブル作成

aws dynamodb create-table --cli-input-json file://src/test/resources/ddl/SampleTable.json

テストデータの登録

aws dynamodb put-item --table-name SampleTable \
  --item '{"pkey": {"S": "test0"}, "skey": {"S": "2018-01-01T00:00:00.001"}, "stringData": {"S": "testdata-001"} }'
aws dynamodb put-item --table-name SampleTable \
  --item '{"pkey": {"S": "test0"}, "skey": {"S": "2018-01-01T00:00:00.002"}, "stringData": {"S": "testdata-002"} }'
aws dynamodb put-item --table-name SampleTable \
  --item '{"pkey": {"S": "test0"}, "skey": {"S": "2018-01-01T00:00:00.003"}, "stringData": {"S": "testdata-003"} }'
aws dynamodb put-item --table-name SampleTable \
  --item '{"pkey": {"S": "test0"}, "skey": {"S": "2018-01-01T00:00:00.004"}, "stringData": {"S": "testdata-004"} }'
aws dynamodb put-item --table-name SampleTable \
  --item '{"pkey": {"S": "test0"}, "skey": {"S": "2018-01-01T00:00:00.005"}, "stringData": {"S": "testdata-005"} }'


処理(CRUD)の作成

検索処理(scan)

src/main/java/ScanTable.java

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.ScanRequest;
import com.amazonaws.services.dynamodbv2.model.ScanResult;

import java.util.List;
import java.util.Map;

public class ScanTable {

    private static AmazonDynamoDB amazonDynamoDB = AmazonDynamoDBClientBuilder.standard().build();

    public static void main(String[] args){

        ScanRequest request = new ScanRequest("SampleTable");
        ScanResult result = amazonDynamoDB.scan(request);
        Integer count = result.getCount();
        System.out.println("#########################################");
        System.out.println("count: " + count );
        List<Map<String,AttributeValue>> items = result.getItems();
        for (Map<String,AttributeValue> item : items) {
            System.out.println(item);
        }   
        System.out.println("#########################################");
    }   

}

テスト実行

gradle run -Pmain=ScanTable


登録処理

src/main/java/PutItem.java

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.PutItemResult;

import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class PutItem {

    private static AmazonDynamoDB amazonDynamoDB = AmazonDynamoDBClientBuilder.standard().build();

    public static void main(String[] args){

        String datetime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS"));

        String pkey = "test1";
        String skey = datetime;
        String stringData = "testdata-" + UUID.randomUUID().toString();

        Map<String,AttributeValue> item = new HashMap<String,AttributeValue>();
        item.put("pkey"       ,   new AttributeValue().withS(pkey));
        item.put("skey"       ,   new AttributeValue().withS(skey));
        item.put("stringData" ,   new AttributeValue().withS(stringData));

        PutItemResult result = amazonDynamoDB.putItem(new PutItemRequest("SampleTable", item));

        System.out.println("#########################################");
        System.out.println(result);
        System.out.println("#########################################");
    }   
}

テスト実行

gradle run -Pmain=PutItem


検索処理(query)

src/main/java/QueryTable.java

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.QueryRequest;
import com.amazonaws.services.dynamodbv2.model.QueryResult;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class QueryTable {

    private static AmazonDynamoDB amazonDynamoDB = AmazonDynamoDBClientBuilder.standard().build();

    public static void main(String[] args){

        QueryRequest request = new QueryRequest("SampleTable");

        Map<String,Condition> keyConditions = new HashMap<String,Condition>();
        keyConditions.put("pkey", new Condition().withComparisonOperator(ComparisonOperator.EQ).withAttributeValueList(new AttributeValue("test1")));
        request.setKeyConditions(keyConditions);
        
        // KeyConditionExpression, ExpressionAttributeNames, ExpressionAttributeValues を使用する場合
        /*
        request.setKeyConditionExpression("#pkey = :pkey");
        request.setExpressionAttributeNames(new HashMap<String,String>(){
            {put("#pkey", "pkey");}
        });
        request.setExpressionAttributeValues(new HashMap<String,AttributeValue>(){
            {put(":pkey", new AttributeValue("test1"));}
        });
        */

        QueryResult result = amazonDynamoDB.query(request);
        Integer count = result.getCount();
        System.out.println("#########################################");
        System.out.println("count: " + count );
        List<Map<String,AttributeValue>> items = result.getItems();
        for (Map<String,AttributeValue> item : items) {
            System.out.println(item);
        }   
        System.out.println("#########################################");
    }   
}

テスト実行

gradle run -Pmain=QueryTable


更新処理(update)

src/main/java/UpdateItem.java

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest;
import com.amazonaws.services.dynamodbv2.model.UpdateItemResult;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class UpdateItem {

    private static AmazonDynamoDB amazonDynamoDB = AmazonDynamoDBClientBuilder.standard().build();

    public static void main(String[] args){

        Map<String, String> attributeNames = new HashMap<String,String>(){{
            put("#stringData", "stringData");
        } }; 

        Map<String, AttributeValue> attributeValues = new HashMap<String, AttributeValue>(){{
            put(":stringData", new AttributeValue().withS("testdata-" + UUID.randomUUID().toString()));
        } }; 

        Map<String, AttributeValue> key = new HashMap<String, AttributeValue>();
        key.put("pkey", new AttributeValue().withS("test0"));
        key.put("skey", new AttributeValue().withS("2018-01-01T00:00:00.001"));

        UpdateItemRequest request = new UpdateItemRequest()
            .withTableName("SampleTable")
            .withKey(key)
            //.withConditionExpression("#other = :other")   // 条件付き更新を行う場合
            .withUpdateExpression("set #stringData = :stringData")
            .withExpressionAttributeNames(attributeNames)
            .withExpressionAttributeValues(attributeValues);

        UpdateItemResult result = amazonDynamoDB.updateItem(request);

        System.out.println("#########################################");
        System.out.println(result);
        System.out.println("#########################################");
    }   
}

テスト実行

gradle run -Pmain=UpdateItem


削除処理(delete)

src/main/java/DeleteItem.java

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.DeleteItemRequest;
import com.amazonaws.services.dynamodbv2.model.DeleteItemResult;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class DeleteItem {

    private static AmazonDynamoDB amazonDynamoDB = AmazonDynamoDBClientBuilder.standard().build();

    public static void main(String[] args){

        Map<String, AttributeValue> key = new HashMap<String, AttributeValue>();
        key.put("pkey", new AttributeValue().withS("test0"));
        key.put("skey", new AttributeValue().withS("2018-01-01T00:00:00.001"));

        DeleteItemRequest request = new DeleteItemRequest()
            .withTableName("SampleTable")
            .withKey(key);

        DeleteItemResult result = amazonDynamoDB.deleteItem(request);

        System.out.println("#########################################");
        System.out.println(result);
        System.out.println("#########################################");
    }   
}

テスト実行

gradle run -Pmain=DeleteItem



トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-09-09 (日) 23:12:32 (91d)