DynamoDB Mapper for Kotlin(プレビュー版)を試してみた

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. エンティティの定義

ユーザはデータクラスに@DynamoDbItemDynamoDbPartitionKeyなどのアノテーションを追加すれば、テーブルとのマッピングを自動的でやってくれます。

仕組みとして、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と遜色ないくらい機能が増えてくれるといいですね。

この記事をシェアする
著者:酒井亮太郎
シナモロール