Предварительно заполните базу данных комнат

Иногда вам может потребоваться, чтобы ваше приложение запускалось с базой данных, в которую уже загружен определенный набор данных. Это называется предварительным заполнением базы данных. В Room 2.2.0 и более поздних версиях вы можете использовать методы API для предварительного заполнения базы данных Room при инициализации содержимым из предварительно упакованного файла базы данных в файловой системе устройства.

Предварительное заполнение из ресурса приложения

Чтобы предварительно заполнить базу данных Room из предварительно упакованного файла базы данных, который находится в любом месте каталога assets/ вашего приложения, вызовите метод createFromAsset() из вашего объекта RoomDatabase.Builder перед вызовом build() :

Котлин

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

Ява

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

Метод createFromAsset() принимает строковый аргумент, содержащий относительный путь от каталога assets/ до предварительно упакованного файла базы данных.

Предварительное заполнение из файловой системы

Чтобы предварительно заполнить базу данных Room из предварительно упакованного файла базы данных, который расположен в любом месте файловой системы устройства , кроме каталога assets/ вашего приложения, вызовите метод createFromFile() из вашего объекта RoomDatabase.Builder перед вызовом build() :

Котлин

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

Ява

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

Метод createFromFile() принимает аргумент File для предварительно упакованного файла базы данных. Room создает копию указанного файла, а не открывает его напрямую, поэтому убедитесь, что у вашего приложения есть разрешения на чтение файла.

Обработка миграций, включающих предварительно упакованные базы данных.

Предварительно упакованные файлы базы данных также могут изменить способ обработки резервной миграции в базе данных Room. Обычно, когда деструктивная миграция включена и Room должен выполнить миграцию без пути миграции, Room удаляет все таблицы в базе данных и создает пустую базу данных с указанной схемой для целевой версии. Однако если вы включите предварительно упакованный файл базы данных с тем же номером, что и целевая версия, Room попытается заполнить вновь созданную базу данных содержимым предварительно упакованного файла базы данных после выполнения деструктивной миграции.

Дополнительную информацию о миграции баз данных комнат см. в разделе Миграция баз данных комнат .

В следующих разделах представлено несколько примеров того, как это работает на практике.

Пример. Резервная миграция с предварительно упакованной базой данных.

Предположим следующее:

  • Ваше приложение определяет базу данных Room версии 3.
  • Экземпляр базы данных, который уже установлен на устройстве, имеет версию 2.
  • Существует предварительно упакованный файл базы данных версии 3.
  • Не существует реализованного пути перехода с версии 2 на версию 3.
  • Разрушительные миграции включены.

Котлин

// 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.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .fallbackToDestructiveMigration()
    .build()

Ява

// 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() , резервная миграция является разрушительной. Room удаляет экземпляр базы данных, установленный на устройстве.
  4. Поскольку существует предварительно упакованный файл базы данных версии 3, Room воссоздает базу данных и заполняет ее, используя содержимое предварительно упакованного файла базы данных. С другой стороны, если у вас есть предварительно упакованный файл базы данных версии 2, Room заметит, что он не соответствует целевой версии, и не будет использовать его как часть резервной миграции.

Пример: реализована миграция с предварительно упакованной базой данных.

Вместо этого предположим, что ваше приложение реализует путь миграции с версии 2 на версию 3:

Котлин

// 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.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_2_3)
    .build()

Ява

// 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, Room запускает определенный метод migrate() для обновления экземпляра базы данных на устройстве до версии 3, сохраняя данные, которые уже находятся в базе данных. Room не использует предварительно упакованный файл базы данных, поскольку Room использует предварительно упакованные файлы базы данных только в случае резервной миграции.

Пример. Многоэтапная миграция с предварительно упакованной базой данных.

Предварительно упакованные файлы базы данных также могут влиять на миграцию, состоящую из нескольких этапов. Рассмотрим следующий случай:

  • Ваше приложение определяет базу данных Room версии 4.
  • Экземпляр базы данных, который уже установлен на устройстве, имеет версию 2.
  • Существует предварительно упакованный файл базы данных версии 3.
  • Существует реализованный путь миграции с версии 3 на версию 4, но не с версии 2 на версию 3.
  • Разрушительные миграции включены.

Котлин

// 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.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_3_4)
    .fallbackToDestructiveMigration()
    .build()

Ява

// 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() , резервная миграция является разрушительной. Room удаляет экземпляр базы данных на устройстве.
  4. Поскольку существует предварительно упакованный файл базы данных версии 3, Room воссоздает базу данных и заполняет ее, используя содержимое предварительно упакованного файла базы данных.
  5. База данных, установленная на устройстве, теперь имеет версию 3. Поскольку она все еще ниже версии, определенной в вашем приложении, необходима еще одна миграция.
  6. Поскольку существует реализованный путь миграции с версии 3 на версию 4, Room запускает определенный методmigr migrate() для обновления экземпляра базы данных на устройстве до версии 4, сохраняя данные, которые были скопированы из предварительно упакованного файла базы данных версии 3.

Дополнительные ресурсы

Чтобы узнать больше о предварительном заполнении базы данных Room, см. следующие дополнительные ресурсы.

Видео

Блоги