Spring Data DynamoDBでSpringからDynamoDBにアクセスする
はじめに
Spring BootからDynamoDBにアクセスする際、まず考えるのがAWS SDK for Javaを使うことだと思います(少なくとも私はそうでした)。ですが、もう少しSpringと親和性が高い方法もあるのではないかと思い調べたところSpring Data DynamoDBを見つけました。今回はこのライブラリの使用方法について書きたいと思います。
手順について
ではライブラリの使用手順についてです。Spring Data DynamoDBの使用例をベースとしておりますが
- AWSのアクセスキー・シークレットキーをクレデンシャルより取得するようにした
- CRUDを全て試したみた
などを変更しております。
1.DynamoDBの準備
まずは今回データを登録するDynamoDBをAWS上に作成します。AWSコンソール上で以下のようにテーブルを作成しました。
- テーブル名 ・・・ SpringUser
- プライマリキー ・・・ id
2.build.gradle
以降はプログラムについてです。今回はGradleを使用したのでbuild.gradleに以下のように記述しました。
buildscript { ext { springBootVersion = '1.3.5.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'spring-boot' jar { baseName = 'SpringBootDynamoDBSample' version = '0.0.1-SNAPSHOT' } sourceCompatibility = 1.8 targetCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-starter') compile group: 'com.github.derjust', name: 'spring-data-dynamodb', version: '4.2.3' testCompile('org.springframework.boot:spring-boot-starter-test') } eclipse { classpath { containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8' } }
build.gradleのベースはSpring Initializrで作成したプロジェクトのものです。これに「spring-data-dynamodb」を追加しました(31行目)。
3.SpringUserクラス
DynamoDBに作成したSpringDataテーブルに対応するクラスです。idの他にfirstName、lastNameを属性として持たせました。
SpringUser.java
package com.example; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; @DynamoDBTable(tableName = "SpringUser") public class SpringUser { private String id; private String firstName; private String lastName; public SpringUser(){ } public SpringUser(String firstName, String lastName){ this.firstName = firstName; this.lastName = lastName; } @DynamoDBHashKey @DynamoDBAutoGeneratedKey public String getId() { return id; } @DynamoDBAttribute public String getFirstName() { return firstName; } @DynamoDBAttribute public String getLastName() { return lastName; } public void setId(String id){ this.id = id; } public void setFirstName(String firstName){ this.firstName = firstName; } public void setLastName(String lastName){ this.lastName = lastName; } }
クラス名には「@DynamoDBTable」アノテーションで対応するテーブル名を、Getterにもそれぞれ対応するアノテーションを付与しています。
4.SpringUserRepositoryクラス
データを操作するためのリポジトリです。以下のようになります。
SpringUserRepository.java
package com.example.repositories; import java.util.List; import org.socialsignin.spring.data.dynamodb.repository.EnableScan; import org.springframework.data.repository.CrudRepository; import com.example.SpringUser; @EnableScan public interface SpringUserRepository extends CrudRepository<SpringUser, String> { List<SpringUser> findByLastName(String lastName); }
5.DynamoDBConfigクラスとapplication.yml
DynamoDBへの接続を定義するDynamoDBConfigクラスと、定義ファイルであるapplication.ymlです。先にも書いたようにDynamoDBConfigクラスでは、AWSのアクセスキー・シークレットキーをアプリ内で保持せず、クレデンシャル(~/.aws/credentialsなど)から取得するようにしました。
DynamoDBConfig.java
package com.example; import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; @Configuration @EnableDynamoDBRepositories(basePackages = "com.example.repositories") public class DynamoDBConfig { @Value("${amazon.dynamodb.endpoint}") private String amazonDynamoDBEndpoint; @Value("${amazon.credential.profile}") private String profile; @Bean public AmazonDynamoDB amazonDynamoDB() { AmazonDynamoDB amazonDynamoDB = new AmazonDynamoDBClient(amazonAWSCredentials()); if (!StringUtils.isEmpty(amazonDynamoDBEndpoint)) { amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint); } return amazonDynamoDB; } @Bean public AWSCredentials amazonAWSCredentials() { return new ProfileCredentialsProvider(profile).getCredentials(); } }
application.yml
amazon: dynamodb: endpoint: https://dynamodb.ap-northeast-1.amazonaws.com credential: profile: default
DynamoDBConfigクラスはapplication.yml内の定義値(endpoint、profile)を読み取って使用しています。application.ymlのprofileについては、クレデンシャル(~/.aws/credentialsなど)に定義した任意のプロファイル名としてください。
6.Applicationクラス
最後に、ここまで書いたクラスを利用するApplicationクラスです。DynamoDBにデータを登録し、抽出・更新・削除を行います。
Application.java
package com.example; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import com.example.repositories.SpringUserRepository; @SpringBootApplication public class Application { @Autowired private SpringUserRepository repository; public static void main(String[] args) { try (ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args)) { Application app = ctx.getBean(Application.class); app.run(args); } catch (Exception e) { e.printStackTrace(); } } public void run(String... args) throws Exception { System.out.println("処理開始"); SpringUser taro = new SpringUser("taro", "yamada"); repository.save(taro); SpringUser jiro = new SpringUser("jiro", "yamada"); repository.save(jiro); SpringUser saburo = new SpringUser("saburo", "yamada"); repository.save(saburo); SpringUser takeshi = new SpringUser("takeshi", "suzuki"); repository.save(takeshi); List<SpringUser> result = repository.findByLastName("yamada"); for(SpringUser user : result){ System.out.println(user.getFirstName() + " " + user.getLastName()); } jiro.setLastName("tanaka"); repository.save(jiro); repository.delete(saburo); System.out.println("処理終了"); } }
まとめ
Spring Data DynamoDBを使い、CRUDができることが確認できました。リポジトリを通してデータの更新を行うところなどが、DynamoDB固有の処理を上手く隠蔽化しているのではと感じます。何かの時に参考になれば幸いです。