Wstępne wypełnianie bazy danych sal

Czasami możesz chcieć, aby aplikacja zaczynała się od bazy danych, która zawiera już określony zbiór danych. Jest to tzw. wstępne wypełnianie bazy danych. W sali 2.2.0 lub nowszej możesz używać metod API do wstępnego wypełniania bazy danych pomieszczenia przy inicjowaniu zawartości ze wstępnie spakowanego pliku bazy danych w systemie plików urządzenia.

Wypełnianie wstępnie na podstawie komponentu z linkiem do aplikacji

Aby wstępnie wypełnić bazę danych Room ze wstępnie spakowanego pliku bazy danych, który znajduje się w dowolnym miejscu w katalogu assets/ aplikacji, przed wywołaniem build() wywołaj metodę createFromAsset() z obiektu RoomDatabase.Builder:

Kotlin

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

Java

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

Metoda createFromAsset() akceptuje argument w postaci ciągu znaków, który zawiera względną ścieżkę z katalogu assets/ do wstępnie spakowanego pliku bazy danych.

Wypełnij wstępnie z systemu plików

Aby wstępnie wypełnić bazę danych sal ze wstępnie spakowanego pliku bazy danych, który znajduje się w dowolnym miejscu w systemie plików urządzenia oprócz katalogu assets/ aplikacji, przed wywołaniem build() wywołaj metodę createFromFile() z obiektu RoomDatabase.Builder:

Kotlin

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

Java

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

Metoda createFromFile() akceptuje argument File dla wstępnie spakowanego pliku bazy danych. Usługa Room tworzy kopię wskazanego pliku, zamiast otwierać go bezpośrednio, dlatego upewnij się, że aplikacja ma uprawnienia do odczytu tego pliku.

Obsługuj migracje obejmujące gotowe bazy danych

Wstępnie spakowane pliki bazy danych mogą też zmieniać sposób, w jaki baza danych sal obsługuje migracje zapasowe. Zazwyczaj, gdy włączone są niszczycielskie migracje, a sala musi przeprowadzić migrację bez ścieżki migracji, sala pomija wszystkie tabele w bazie danych i tworzy pustą bazę danych o określonym schemacie dla wersji docelowej. Jeśli jednak dołączysz gotowy plik bazy danych o tym samym numerze co wersja docelowa, po przeprowadzeniu niszczycielskiej migracji nowo odtworzona baza danych będzie próbowała wypełnić nowo utworzoną bazę danych zawartością tego pliku.

Więcej informacji na temat migracji baz danych sal znajdziesz w artykule na temat migracji baz danych sal.

Poniższe sekcje zawierają kilka przykładów, które pokazują, jak to działa w praktyce.

Przykład: migracja zastępcza przy użyciu gotowej bazy danych

Załóżmy, że:

  • Aplikacja definiuje bazę danych Room w wersji 3.
  • Instancja bazy danych, która jest już zainstalowana na urządzeniu, ma wersję 2.
  • Istnieje gotowy plik bazy danych w wersji 3.
  • Brak wdrożonej ścieżki migracji z wersji 2 do 3.
  • Niszczycielskie migracje są włączone.

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.java, "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();

Oto co dzieje się w tej sytuacji:

  1. Ponieważ baza danych zdefiniowana w aplikacji jest w wersji 3, a instancja jest już zainstalowana na urządzeniu w wersji 2, migracja jest konieczna.
  2. Ze względu na to, że nie ma wdrożonego planu migracji z wersji 2 do 3, migracja jest migracją zastępczą.
  3. Ponieważ wywoływana jest metoda kreatora fallbackToDestructiveMigration(), migracja zastępcza jest szkodliwa. Sala pomija instancję bazy danych zainstalowaną na urządzeniu.
  4. W wersji 3 znajduje się gotowy plik bazy danych, więc funkcja Room odtwarza bazę danych i wypełnia ją przy użyciu zawartości tego pliku. Jeśli z drugiej strony gotowy plik bazy danych znajduje się w wersji 2, aplikacja Room poinformuje, że nie pasuje do wersji docelowej, i nie użyje jej w ramach migracji zastępczej.

Przykład: wdrożona migracja przy użyciu gotowej bazy danych

Załóżmy, że Twoja aplikacja wdraża ścieżkę migracji z wersji 2 do wersji 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.java, "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();

Oto co dzieje się w tej sytuacji:

  1. Ponieważ baza danych zdefiniowana w aplikacji jest w wersji 3, a baza danych już zainstalowana na urządzeniu jest w wersji 2, migracja jest niezbędna.
  2. Ze względu na to, że istnieje wdrożona ścieżka migracji z wersji 2 do wersji 3, sala uruchamia zdefiniowaną metodę migrate(), aby zaktualizować instancję bazy danych na urządzeniu do wersji 3 przy zachowaniu danych, które już znajdują się w bazie danych. Sala nie używa gotowego pliku bazy danych, ponieważ funkcja Room korzysta z gotowych plików bazy danych tylko w przypadku migracji zastępczej.

Przykład: migracja wieloetapowa za pomocą gotowej bazy danych

Wstępnie spakowane pliki bazy danych również mogą wpływać na migracje składające się z wielu etapów. Weź pod uwagę taki przypadek:

  • Aplikacja definiuje bazę danych Room w wersji 4.
  • Instancja bazy danych, która jest już zainstalowana na urządzeniu, ma wersję 2.
  • Istnieje gotowy plik bazy danych w wersji 3.
  • Istnieje wdrożona ścieżka migracji z wersji 3 do 4, ale nie z wersji 2 do 3.
  • Niszczycielskie migracje są włączone.

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.java, "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();

Oto co dzieje się w tej sytuacji:

  1. Ponieważ baza danych zdefiniowana w aplikacji jest w wersji 4, a instancja jest już zainstalowana na urządzeniu w wersji 2, migracja jest konieczna.
  2. Ze względu na to, że nie ma wdrożonej ścieżki migracji z wersji 2 do 3, migracja jest migracją zastępczą.
  3. Ponieważ wywoływana jest metoda kreatora fallbackToDestructiveMigration(), migracja zastępcza jest szkodliwa. Sala usuwa instancję bazy danych na urządzeniu.
  4. W wersji 3 znajduje się gotowy plik bazy danych, więc funkcja Room odtwarza bazę danych i wypełnia ją przy użyciu zawartości tego pliku.
  5. Baza danych zainstalowana na urządzeniu jest teraz w wersji 3. Wartość nadal jest niższa od wersji zdefiniowanej w aplikacji, dlatego konieczna jest kolejna migracja.
  6. Ze względu na to, że istnieje wdrożona ścieżka migracji z wersji 3 do 4, sala uruchamia zdefiniowaną metodę migrate(), aby zaktualizować instancję bazy danych na urządzeniu do wersji 4, zachowując dane skopiowane ze wstępnie spakowanego pliku bazy danych w wersji 3.

Dodatkowe materiały

Więcej informacji o wstępnym wypełnianiu bazy danych sal znajdziesz w tych materiałach dodatkowych.

Filmy

Blogi