Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

Room データベースを事前に取り込む

アプリを起動する際に、特定のデータセットをすでに読み込んでいるデータベースを使用したい場合があります。これは、データベースの事前取り込みと呼ばれます。Room 2.2.0 以降では、API メソッドを使用して、初期化時にデバイスのファイル システム内にある事前パッケージ化済みデータベース ファイルの内容を Room データベースに事前取り込みできます。

アプリアセットから事前取り込みする

事前パッケージ化済みデータベース ファイルから Room データベースに事前取り込みする際、データベース ファイルがアプリの assets/ ディレクトリ内にある場合には、次のように、RoomDatabase.Builder オブジェクトから createFromAsset() メソッドを呼び出してから、build() を呼び出します。

Kotlin

    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .build()
    

Java

    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .build();
    

createFromAsset() メソッドは、事前パッケージ化済みデータベース ファイルへの assets/ ディレクトリからの相対パスが入った文字列を受け付けます。

ファイル システムから事前取り込みする

事前パッケージ化済みデータベース ファイルから Room データベースを事前取り込みする際、データベース ファイルがデバイスのファイル システムでアプリの assets/ ディレクトリの外にある場合には、RoomDatabase.Builder オブジェクトから createFromFile() メソッドを呼び出してから、build() を呼び出します。

Kotlin

    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromFile(File("mypath"))
        .build()
    

Java

    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromFile(new File("mypath"))
        .build();
    

createFromFile() メソッドは、事前パッケージ化済みデータベース ファイルの File 引数を受け付けます。Room で指定されたファイルが直接開かれるのではなく、コピーが作成されるため、アプリにファイルの読み取り権限があることを確認してください。

事前パッケージ化済みデータベースを含む移行の処理

事前パッケージ化済みデータベース ファイルによって、Room データベースでのフォールバック移行の処理方法も変わります。通常、破壊的移行が有効で、Room が移行パスなしで移行を実行する必要がある場合、Room はデータベース内のすべてのテーブルを削除し、ターゲット バージョンの指定されたスキーマで空のデータベースを作成します。ただし、ターゲット バージョンと同じ番号の事前パッケージ化済みデータベース ファイルを含めると、破壊的移行の実行後に、事前パッケージ化済みデータベース ファイルの内容が新規に再作成されたデータベースに取り込まれます。

Room データベースの移行の詳細については、Room データベースを移行するをご覧ください。

次のセクションでは、実際の動作の例を紹介します。

例: 事前パッケージ化済みデータベースを含むフォールバック移行

次の前提で説明します。

  • バージョン 3 で Room データベースを定義している。
  • デバイスにインストールされているデータベース インスタンスはバージョン 2 である。
  • バージョン 3 の事前パッケージ化済みデータベース ファイルがある。
  • バージョン 2 からバージョン 3 への移行パスは実装されていない。
  • 破壊的移行が有効になっている。

Kotlin

    // Database class definition declaring version 3.
    @Database(version = 3)
    abstract class AppDatabase : RoomDatabase() {
        ...
    }

    // Destructive migrations are enabled and a prepackaged database
    // is provided.
    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .fallbackToDestructiveMigration()
        .build()
    

Java

    // Database class definition declaring version 3.
    @Database(version = 3)
    public abstract class AppDatabase extends RoomDatabase {
        ...
    }

    // Destructive migrations are enabled and a prepackaged database
    // is provided.
    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .fallbackToDestructiveMigration()
        .build();
    

この場合は、次のようになります。

  1. アプリで定義されたデータベースがバージョン 3 で、デバイスにインストールされているデータベース インスタンスがバージョン 2 であるため、移行が必要です。
  2. バージョン 2 からバージョン 3 への移行プランが実装されていないため、この移行はフォールバック移行です。
  3. fallbackToDestructiveMigration() ビルダー メソッドが呼び出されるため、フォールバック移行は破壊的移行です。デバイスにインストールされているデータベース インスタンスが削除されます。
  4. バージョン 3 の事前パッケージ化済みデータベースがあるため、データベースが再作成され、事前パッケージ化済みデータベース ファイルの内容が取り込まれます。事前パッケージ化済みデータベース ファイルがバージョン 2 の場合は、ターゲット バージョンと一致せず、フォールバック移行では使用されないことが通知されます。

例: 事前パッケージ化済みデータベースを含む実装済みの移行

次のように、バージョン 2 からバージョン 3 への移行パスを実装するとします。

Kotlin

    // Database class definition declaring version 3.
    @Database(version = 3)
    abstract class AppDatabase : RoomDatabase() {
        ...
    }

    // Migration path definition from version 2 to version 3.
    val MIGRATION_2_3 = object : Migration(2, 3) {
        override fun migrate(database: SupportSQLiteDatabase) {
            ...
        }
    }

    // A prepackaged database is provided.
    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .addMigrations(MIGRATION_2_3)
        .build()
    

Java

    // Database class definition declaring version 3.
    @Database(version = 3)
    public abstract class AppDatabase extends RoomDatabase {
        ...
    }

    // Migration path definition from version 2 to version 3.
    static final Migration MIGRATION_2_3 = new Migration(2, 3) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            ...
        }
    };

    // A prepackaged database is provided.
    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .addMigrations(MIGRATION_2_3)
        .build();
    

この場合は、次のようになります。

  1. アプリで定義されたデータベースはバージョン 3 で、デバイスにインストールされているデータベースはバージョン 2 であるため、移行が必要です。
  2. バージョン 2 からバージョン 3 への移行パスが実装されているため、定義されている migrate() メソッドが実行され、すでにデータベースにあるデータを維持したまま、デバイス上のデータベース インスタンスがバージョン 3 に更新されます。フォールバック移行の場合にのみ事前パッケージ化済みデータベース ファイルが使用されるため、事前パッケージ化済みデータベース ファイルは使用されません。

例: 事前パッケージ化済みデータベースを含むマルチステップ移行

事前パッケージ化済みデータベース ファイルは、複数のステップで構成される移行にも影響します。次の場合を考えます。

  • バージョン 4 で Room データベースを定義している。
  • デバイスにインストールされているデータベース インスタンスはバージョン 2 である。
  • バージョン 3 の事前パッケージ化済みデータベース ファイルがある。
  • バージョン 3 からバージョン 4 への移行パスは実装されているが、バージョン 2 からバージョン 3 への移行パスは実装されていない。
  • 破壊的移行が有効になっている。

Kotlin

    // Database class definition declaring version 4.
    @Database(version = 4)
    abstract class AppDatabase : RoomDatabase() {
        ...
    }

    // Migration path definition from version 3 to version 4.
    val MIGRATION_3_4 = object : Migration(3, 4) {
        override fun migrate(database: SupportSQLiteDatabase) {
            ...
        }
    }

    // Destructive migrations are enabled and a prepackaged database is
    // provided.
    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .addMigrations(MIGRATION_3_4)
        .fallbackToDestructiveMigration()
        .build()
    

Java

    // Database class definition declaring version 4.
    @Database(version = 4)
    public abstract class AppDatabase extends RoomDatabase {
        ...
    }

    // Migration path definition from version 3 to version 4.
    static final Migration MIGRATION_3_4 = new Migration(3, 4) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            ...
        }
    };

    // Destructive migrations are enabled and a prepackaged database is
    // provided.
    Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .addMigrations(MIGRATION_3_4)
        .fallbackToDestructiveMigration()
        .build();
    

この場合は、次のようになります。

  1. アプリで定義されたデータベースがバージョン 4 で、デバイスにインストールされているデータベース インスタンスがバージョン 2 であるため、移行が必要です。
  2. バージョン 2 からバージョン 3 への移行パスが実装されていないため、この移行はファールバック移行です。
  3. fallbackToDestructiveMigration() ビルダー メソッドが呼び出されるため、フォールバック移行は破壊的移行です。デバイス上のデータベース インスタンスは削除されます。
  4. バージョン 3 の事前パッケージ化済みデータベースがあるため、データベースが再作成され、事前パッケージ化済みデータベース ファイルの内容が取り込まれます。
  5. デバイスにインストールされているデータベースはバージョン 3 になります。アプリで定義されているバージョンよりもまだ小さいため、移行がもう 1 回必要です。
  6. バージョン 3 からバージョン 4 への移行パスが実装されているため、定義されている migrate() メソッドが実行され、バージョン 3 の 事前パッケージ化済みデータベース ファイルから上書きコピーされたデータを維持したまま、デバイス上のデータベース インスタンスをバージョン 4 に更新します。

参考情報

Room データベースの事前取り込みの詳細については、以下のリソースもご覧ください。

動画

ブログ