DynamoDB Mapper for Kotlin(プレビュー版)を試してみた
目次
はじめに
AWS SDK for Kotlin に新しく追加された DynamoDB Mapper(プレビュー版)を試してみました。従来の DynamoDB Client や Java の DynamoDB Enhanced Client と比較しながら、その特徴を紹介します。
Codespacesで動作するコードを公開しています。
DynamoDB Mapper for Kotlin の特徴
利点
- Kotlin のデータクラスとの親和性が高いコード生成による型安全性の確保
- Kotlin らしい DSL による直感的な APIコルーチンのサポート
注意点
- まだプレビュー版のため API が変更される可能性がある一部機能が未実装
- ドキュメントが少ない
基本的な使い方
1. エンティティの定義
ユーザはデータクラスに@DynamoDbItem
や DynamoDbPartitionKey
などのアノテーションを追加すれば、テーブルとのマッピングを自動的でやってくれます。
仕組みとして、Kotlin KSPを使ったコードジェネレータが裏で動いているようです。
@DynamoDbItem
data class Book(
@DynamoDbPartitionKey
val title: String,
@DynamoDbSortKey
val volume: String,
val author: String,
val price: Int,
// ... その他のフィールド
)
2. テーブル操作の例
Kotlinのデータクラスを渡すだけで、データの読み書きができます。
// テーブルの取得
val table = DynamoDbMapper(ddb).getTable(Book.TABLE_NAME, BookSchema)
// アイテムの保存
table.putItem {
item = Book(
title = "1から始めるKotlin",
volume = "1",
author = "著者名",
price = 1000
)
}
// アイテムの取得
val book = table.getItem {
key = Book(
title = "1から始めるKotlin",
volume = "1",
author = "", // キー以外のフィールドは無視される
price = 0
)
}.item
ただ、getItemの方は、ちょっとクセがありますね。本来渡したいのは、DynamoDBの主キーだけのはずなのですが、必要がないはずの属性も渡すことになります。(上の例だと、キーはtitleとvolumeで、authorは必要がないはず)
この問題に対しては、`getItem(partitonKey: PK, sortKey: SK)`というオーバーロードが開発中のようなので、こちらを使うようにすれば問題なさそうです。
従来の実装との比較
通常の Kotlin SDKのDynamoDB Client との比較
- 従来: AttributeValue の手動マッピングが必要
- DynamoDB Mapper: データクラスを直接使用可能
Java SDK の Enhanced Client との比較
- 従来: ビルダーパターンによる冗長な記述
- DynamoDB Mapper: DSL による簡潔な記述
制約(おそらくプレビュー版のみの制約と思われる)
GSIやLSIのスキーマを宣言的に書くようなアノテーションはない。
現状は、ItemSchemaというスキーマを定義するクラスを明示的に呼ぶ必要があります。(ちなみにJavaのEnhancedClientにはある)
射影する属性が元テーブルと同じ(All Attributes)時は、コンバーター(ユーザのデータクラスとDynamoDBのテーブルクラスを相互変換する)には、自動生成されたものが使えます。
val lsi = table.getIndex(
name = "books-lsi-by-rate",
schema = ItemSchema(
converter = BookConverter, // これはデータクラスBookから、自動生成されるクラス
partitionKey = KeySpec.String("title"),
sortKey = KeySpec.Number("rate")
)
)
キーのみを射影する(Table and Index Keys)時や、射影する属性を選択する(Specify Attributes)時は、コンバーターも自作しないといけないようです。詳しくは、ドキュメントを参照してください。
そのほか機能は限定的
- 作成予定だが、未実装のメソッドがある(テーブル作成や削除など)
- トランザクションが未対応(対応予定があるかは未調査)
セットアップ
build.gradle.ktsには次のようにプラグインと依存関係の追加が必要です。詳しくはドキュメントを参照してください。
plugins {
...
// DynamoDB Mapper
id("aws.sdk.kotlin.hll.dynamodbmapper.schema.generator") version "1.3.98-beta" // For the Developer Preview, use the beta version of the latest SDK.
...
}
val awsSdkVersion: String = "1.3.98"
dependencies {
...
// DynamoDB Mapper
implementation("aws.sdk.kotlin:dynamodb-mapper:${awsSdkVersion}-beta")
implementation("aws.sdk.kotlin:dynamodb-mapper-annotations:${awsSdkVersion}-beta")
...
}
まとめ
まだプレビュー版で、機能は限定的です。GAの際に、どれくらい作り込まれているかはわからないですが、通常のKotlin用DynamoDB Clientを使っている人は、対応している機能だけでも使ってみるといいと思います。JavaのEnhancedClientを使っている人は、Java版SDK特有のビルダーパターンが使いにくいな、Kotlinコルーチン使いたいな、と思ったら、乗り換えても良いかもですね。
KotlinのAWS SDKがGAになって1年経ちますが、ちょっとずつ機能が増えていますね。早くJava SDKと遜色ないくらい機能が増えてくれるといいですね。