Room Database:データの事前取り込み

投稿日:  更新日:

アプリケーションが始めて起動した直後に、データの事前取り込み(初期状態の設定)を必要とする場合があります。

事前取り込みの方法ついて、まとめました。

Room(Android Jetpack)でデータベースを構築した場合です。

※環境:Android Studio Ladybug | 2024.2.1 Patch 3
    Kotlin 2.0.0
    androidx.sqlite:sqlite:2.4.0
    androidx.room:room-*:2.6.1
    DB Browser for SQLite バージョン 3.13.1

※サンプルの全体像は「Roomでデータベースを構築」を参照

スポンサーリンク

事前取り込みとは

「事前取り込み」とは、アプリケーションが始めて起動した直後の、データベースの初期状態を設定することです。

事前取り込みが必要かどうかはアプリケーションに依存します。ですので、事前取り込みはオプション的な実装です。

スポンサーリンク

事前取り込みの実装

Roomは初期状態をファイルから取り込む機能を持っています。以下は、assetsフォルダから取り込む例です。

assetsフォルダから取り込む

@Database(entities = arrayOf(Player::class), version = 1)
abstract class GameDb : RoomDatabase() {

    abstract fun playerDao(): PlayerDao

    companion object {
        @Volatile
        private var instance: GameDb? = null
        fun getDatabase(context: Context): GameDb {
            return instance ?: synchronized(this) {
                val _instans = Room.databaseBuilder(
                    context,
                    GameDb::class.java,
                    "Game.db"
                )
                    .createFromAsset("databases/Game.db") // 初期状態
                    .build()
                instance = _instans
                _instans
            }
        }
    }
}

ただし、データベース識別子と初期状態は、スキーマが一致していなければなりません。

不一致の場合はエラーになり、アプリは起動しません。

スポンサーリンク

事前データの作成

データベースの初期状態を「事前データ」といいます。

「ツール:DB Browser for SQLite」を用いた、事前データの作成方法を紹介します。
※DB Browser for SQLiteについては「データベースの閲覧」を参照

スキーマ情報のダンプ

事前データの作成で必要なスキーマ情報をダンプします。

build.gradle.ktsファイルにスキーマ情報のダンプ先フォルダを指定して下さい。

plugins { ... }

android {
    namespace = "com.example.game"
    compileSdk = 35

    defaultConfig { ... }
    buildTypes { ... }
    compileOptions { ... }
    kotlinOptions { ... }
    buildFeatures { ... }
    ksp {
        arg("room.schemaLocation", "$projectDir/schemas")
    }
}

dependencies { ... }

※「exportSchema = true」はスキーマのダンプを有効化するフラグです。デフォルトがtrueなので、指定の必要はありません。

@Database(entities = arrayOf(Player::class), version = 1, exportSchema = true)
abstract class GameDb : RoomDatabase() {

    abstract fun playerDao(): PlayerDao     // Daoの提供(必須)

    companion object { ... }
}

アプリを実行すると、指定したフォルダにスキーム情報(jsonファイル)がダンプされます。実行の必要な点が難点です。

スキーマ情報のダンプ

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "1389462589b209bcd420685744427f6a",
    "entities": [
      {
        "tableName": "Player",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `score` INTEGER NOT NULL)",
        "fields": [
          {
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
            "fieldPath": "name",
            "columnName": "name",
            "affinity": "TEXT",
            "notNull": true
          },
          {
            "fieldPath": "score",
            "columnName": "score",
            "affinity": "INTEGER",
            "notNull": true
          }
        ],
        "primaryKey": {
          "autoGenerate": true,
          "columnNames": [
            "id"
          ]
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "views": [],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1389462589b209bcd420685744427f6a')"
    ]
  }
}

スキーマ情報の「identityHashの値」は「entitiesの値」のハッシュ値です。Roomのシステムは、この値を用いてスキーマの一致を確認しています。

データベースの作成

SQLのコマンドファイル(GameDb.sql)を作成します。

スキーマ情報(jsonファイル)のハイライト部分を抜き出した物です。ただし、テーブル名(${TABLE_NAME})は置き換えて下さい。

CREATE TABLE IF NOT EXISTS `Player` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `score` INTEGER NOT NULL);
CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT);
INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1389462589b209bcd420685744427f6a');
※コマンドラインの終わりはセミコロン「;」です。

コマンドファイルをツールにインポートすれば、データベースが作成されます。

事前データのデータベース作成

Rowデータの登録

必要なRowデータを登録して変更を書き込めば、事前データの作成完了です。

事前データのRowデータ登録

作成した事前データは、プロジェクトのassetsフォルダへ、コピー&ペーストして下さい。

スポンサーリンク

事前取り込みの結果

アプリが始めて起動した直後に事前取り込みしたデータが表示されます。

スポンサーリンク

関連記事:

Androidアーキテクチャコンポーネント(AAC)は「堅牢でテストとメンテナンスが簡単なアプリの設計を支援する」とドキュメントで説明されています。 有効そうだけど、実態がよくわからないので、いろいろ調べて理解した内容をまとめました。 ...
Androidは標準でSQLiteというRDBMS(Relational Database Management System)を扱います。 SQLiteは少し個性的なデータベースです。 データベース全般の説明を通して、SQLiteと他の違いをまとめます。 ※環境:Android Studio Ladybug | 2024.2.1 Patch 2     Kotlin 2.0.0 ...
データベースを扱うアプリケーションの開発で、動作を確認するためにデータベースの閲覧が出来ると便利です。 データベースは、マネージメントシステムを介してアクセスされるため、プログラムからブラックボックスに見えます。 ですので、データベース内部の問題は見つけ難いです。 デバックおいてデータベースの閲覧が出来れば、内部の問題を用意に確認できます。 ※環境:Android Studio Ladybug | 2024.2.1 Patch 2     DB Browser for SQLite バージョン 3.13.1 ...
Androidが標準で扱うデータベースはSQLiteです。 ※詳細は「Androidで扱うデータベース」を参照 データベースを構築する方法は「SQLite API(Android SDK)」と「Room(Android Jetpack)」の2通りがあります。 今回は「Room」でデータベースを構築する方法を紹介します。 ※環境:Android Studio Ladybug | 2024.2.1 Patch 2     Kotlin 2.0.0     androidx.sqlite:sqlite:2.4.0     androidx.room:room-*:2.6.1 ...
Roomは処理の開始時にコールバックを受け取ることができます。 このコールバックついて、まとめました。 ※環境:Android Studio Ladybug | 2024.2.1 Patch 3     Kotlin 2.0.0     androidx.sqlite:sqlite:2.4.0     androidx.room:room-*:2.6.1     DB Browser for SQLite バージョン 3.13.1 ※サンプルの全体像は「Roomでデータベースを構築」を参照 ...
Room(Android Jetpack)でデータベースを構築した場合、アプリのパフォーマンスを考えると、識別子の共有が必要になってきます。 この点について、まとめました。 ※環境:Android Studio Ladybug | 2024.2.1 Patch 3     Kotlin 2.0.0     androidx.sqlite:sqlite:2.4.0     androidx.room:room-*:2.6.1 ※サンプルの全体像は「Roomでデータベースを構築」を参照 ...
Room(Android Jetpack)でデータベースを構築した場合、データベースへアクセスする際に、データベースのOpenとCloseという処理を伴います。 この点について、まとめました。 ※環境:Android Studio Ladybug | 2024.2.1 Patch 3     Kotlin 2.0.0     androidx.sqlite:sqlite:2.4.0     androidx.room:room-*:2.6.1 ※サンプルの全体像は「Roomでデータベースを構築」を参照 ...
スポンサーリンク