LoginSignup
1
0

Spring BootからDynamoDBへのアクセス(Spring Cloud AWS 3.0)

Last updated at Posted at 2023-09-18

はじめに

Spring Cloud AWS 3.0を利用してDynamoDBへのアクセス方法をまとめる

環境

  • Java 17
  • Spring Boot 3.1.3
  • Spring Cloud AWS 3.0.2
  • DynamoDB local
  • Gradle 8.2.1

DynamoDB localの設定

  • docker-compose.yamlに下記の定義を行いDynamoDB Localのコンテナを起動
  • dynamodb-adminを追加しているので、http://localhost:8001/にアクセスすればGUIでDynaamoDBに接続できる
docker-compose.yml
version: '3.8'
services:
  dynamodb-local:
    image: amazon/dynamodb-local:latest
    container_name: dynamodb-local
    user: root
    command: -jar DynamoDBLocal.jar -sharedDb -dbPath /data
    volumes:
      - ./data/dynamodb:/data
    ports:
      - "8000:8000"

  dynamo-admin:
    image: aaronshaf/dynamodb-admin:latest
    container_name: dynamo-admin
    environment:
      DYNAMO_ENDPOINT: http://dynamodb-local:8000
    ports:
      - "8001:8001"
    depends_on:
      - dynamodb-local

image.png

build.gradle

  • dependenciesに下記の依存関係を追加
build.gradle
implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.2")
implementation 'io.awspring.cloud:spring-cloud-aws-starter'	
implementation 'io.awspring.cloud:spring-cloud-aws-starter-dynamodb'

application.yml

  • DynamoDBの接続先を設定する(DynamoDB Localのポートを指定)
spring:
  cloud:
    aws:
      dynamodb:
        endpoint: http://localhost:4569
        table-prefix: 

パラメーターについては下記を参照
https://docs.awspring.io/spring-cloud-aws/docs/3.0.2/reference/html/index.html#configuration

spring-devtools.properties

  • spring-boot-devtoolsを依存関係に追加していると下記の例外が発生したので抑止するためにsrc/main/resources/META-INF/spring-devtools.propertiesを作成して下記を追加した
spring-devtools.properties
restart.include.dynamodb=/dynamodb-[-\\w\\d\.]+\.jar
restart.include.awspring=spring-cloud-aws-[-\\w\\d\.]+\.jar

例外

java.lang.IllegalStateException: Failed to execute CommandLineRunner
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:774)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:755)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:319)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
	at com.example.demo.HttpclientApplication.main(HttpclientApplication.java:35)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
Caused by: java.lang.ClassCastException: class com.example.demo.Person cannot be cast to class com.example.demo.Person (com.example.demo.Person is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @6ce9878a; com.example.demo.Person is in unnamed module of loader 'app')
	at software.amazon.awssdk.enhanced.dynamodb.internal.mapper.ResolvedImmutableAttribute.lambda$create$0(ResolvedImmutableAttribute.java:54)
	at software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema.lambda$itemToMap$5(StaticImmutableTableSchema.java:507)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1092)
	at software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema.itemToMap(StaticImmutableTableSchema.java:505)
	at software.amazon.awssdk.enhanced.dynamodb.mapper.WrappedTableSchema.itemToMap(WrappedTableSchema.java:67)
	at software.amazon.awssdk.enhanced.dynamodb.mapper.WrappedTableSchema.itemToMap(WrappedTableSchema.java:67)
	at software.amazon.awssdk.enhanced.dynamodb.internal.operations.PutItemOperation.generateRequest(PutItemOperation.java:90)
	at software.amazon.awssdk.enhanced.dynamodb.internal.operations.PutItemOperation.generateRequest(PutItemOperation.java:45)
	at software.amazon.awssdk.enhanced.dynamodb.internal.operations.CommonOperation.execute(CommonOperation.java:113)
	at software.amazon.awssdk.enhanced.dynamodb.internal.operations.TableOperation.executeOnPrimaryIndex(TableOperation.java:59)
	at software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbTable.putItem(DefaultDynamoDbTable.java:201)
	at software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbTable.putItem(DefaultDynamoDbTable.java:209)
	at software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbTable.putItem(DefaultDynamoDbTable.java:214)
	at io.awspring.cloud.dynamodb.DynamoDbTemplate.save(DynamoDbTemplate.java:59)
	at com.example.demo.HttpclientApplication.run(HttpclientApplication.java:51)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771)
	... 10 common frames omitted

使い方

テーブル定義

  • @DynamoDbBeanをクラスに付与
  • getterに@DynamoDbAttributeを付与
  • パーティションキーのgetterには@DynamoDbPartitionKeyを付与
import java.util.UUID;

import lombok.Data;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;

@DynamoDbBean
@Data
public class Person {
    private UUID id;
    private String name;
    private String lastName;

    @DynamoDbPartitionKey
    @DynamoDbAttribute("id")
    public UUID getId() {
        return id;
    }
    
    @DynamoDbAttribute("name")
    public String getName() {
      return this.name;
    }
    
    @DynamoDbAttribute("lastName")
    public String getLastName() {
      return this.lastName;
    }
}

テーブル作成

  • DynamoDbEnhancedClientを利用する
@Autowired
private DynamoDbEnhancedClient dynamoDbEnhancedClient;

実装例

DynamoDbTable<Person> table = dynamoDbEnhancedClient.table("person", TableSchema.fromBean(Person.class));
table.createTable();

テーブルへの新規アイテム追加

  • DynamoDbTemplateを利用する
@Autowired
private DynamoDbTemplate dynamoDbTemplate;

実装例

Person person = new Person();
person.setId(UUID.randomUUID());
person.setName("name");
person.setLastName("last");

Person save = dynamoDbTemplate.save(person);
log.info("save =[{}]", save); // save =[Person(id=5dac8d41-b5c9-4ef1-abbe-bacccde71ab0, name=name, lastName=last)] 

テーブルのアイテム更新

  • DynamoDbTemplateを利用する
@Autowired
private DynamoDbTemplate dynamoDbTemplate;

実装例

person.setName("update name");
Person update = dynamoDbTemplate.update(person);
log.info("update =[{}]", update); // update =[Person(id=5dac8d41-b5c9-4ef1-abbe-bacccde71ab0, name=update name, lastName=last)] 

テーブルのアイテム検索

  • DynamoDbTemplateを利用する
@Autowired
private DynamoDbTemplate dynamoDbTemplate;

実装例

Person load = dynamoDbTemplate.load(Key.builder().partitionValue(update.getId().toString()).build(), Person.class);
log.info("load =[{}]", load); // load =[Person(id=5dac8d41-b5c9-4ef1-abbe-bacccde71ab0, name=update name, lastName=last)] 

テーブルのアイテム削除

  • DynamoDbTemplateを利用する
@Autowired
private DynamoDbTemplate dynamoDbTemplate;

実装例

dynamoDbTemplate.delete(update);

最後に

  • spring-devtoolsとAWSの相性が悪いのかClassCastExceptionが発生してその部分の解決に苦労したが、それ以外は簡単にDynamoDBに接続ができた
  • 検索系のQueryやScan関係のメソッドについてはまだ調べ切れていないのであとでまとめたい・・・

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0