Spring Data DynamoDBを使う
Spring Data DynamoDBの使い方は、GitHubのプロジェクトページをご参照ください。
バージョンではまる
spring-data-dynamodb 4.5.0だと、上記公式ページのチュートリアルどおりに書いてもなぜかエラーが出るので、Compatibilityの表を見て、同じくSpring Framework4.3以降で使える、4.3.1まで下げると、エラーがでなくなりました。
4.3.1だと発生せず、4.4.x以降だと発生するエラーは下記の通りで
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1102)
... 47 more
Caused by: java.lang.NoSuchMethodException: org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean.<init>()
at java.lang.Class.getConstructor0
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
... 48 more
Publicコンストラクタが無いために見えるのですが、チュートリアルどおりだとrepositoryはinterfaceで、
@EnableScan
public interface XxxRepository extends CrudRepository<Xxx, String> {
実装クラスはSpring framework側でproxyのインスタンスが動的に作成されるはずなので、どう回避したものやら…
#ご存知の方がいらっしゃいましたら、教えて頂けると助かります
エラー「No field annotated with interface org.springframework.data.annotation.Id found!」が発生する
しかし、お試しでハッシュキーだけ使って書くと動作したのに、ハッシュキーとレンジキーの両方をアノテーションで指定すると、途端にこのようなエラーが発生します。
これにはまった方は、こちらのissue報告および回避策のソース[1][2]をご参照ください。
[追記]最終的なガイドのページはこちらのようです。
僕もこれで、動作するようになりました。
ポイントは『ハッシュキーとレンジキーを格納するIDクラスを作成する』ということです。
細かい規則は下記です。
- IDクラスは、Serializableを実装する
- IDクラスには、ハッシュキーとレンジキーのフィールドと、getter/setterを作成する
- IDクラスのハッシュキーのgetterに@DynamoDBHashKeyを、レンジキーのgetterに@DynamoDBRangeKeyを付与する
- 元のEntityクラスは、IDクラスにSpringの@IDアノテーションを付与する
- Entityクラスに、ハッシュキーとレンジキーのgetter/setterを作成し、IDクラスのgetter/setterを呼出す
- このとき、Entityクラスのフィールドにハッシュキーとレンジキーそのものがあるかどうかは特に気にしない
- Entityクラスのハッシュキーのgetterに@DynamoDBHashKeyを、レンジキーのgetterに@DynamoDBRangeKeyを付与する。これはIDクラスのアノテーションと重複する(けど、気にしない)
直接記載はされていませんが、忘れやすいこととして
- RepositoryクラスのGenerics内のIDのクラスは、上記で作製したIDクラスを指定する
#サンプルソースだと、ハッシュキーがThreadIdクラスという少し特殊なクラスなので、Marshallerが定義されていますが、Stringなどがハッシュキーの場合は、@DynamoDBMarshallingの指定は無くて大丈夫です。
こちらのisuue報告でのコメントによると、
Spring-DataとAWS-SDKでのアノテーションがそれぞれあり、Spring-Data-Dynamodbはそれら2つの統合作業なので、どうしてもこのような(アノテーション関連の)エラーが出てしまう、それは驚きではないんだけれども、ということでした。
振り返ると、いろんなページのチュートリアル[1][2][3][4]で、Hashキーだけのサンプルが多いんですが、そういうことなんでしょうかね…
今後
DynamoDBMapperでもアノテーションは実現できているし、spring-data-dynamodbを使って悩まし過ぎるときは、DynamoDBMapperを直接使う(つまり、AWS SDKだけ使う)ようにしてもいいかなと考えています。
以上です。