Raumdatenbank vorab ausfüllen

Manchmal soll Ihre Anwendung mit einer Datenbank beginnen, die bereits mit einem bestimmten Datensatz geladen ist. Dies wird als Vorabausfüllen einer Datenbank bezeichnet. In Room 2.2.0 und höher können Sie API-Methoden verwenden, um eine Raumdatenbank bei der Initialisierung mit Inhalten aus einer vorkonfigurierten Datenbankdatei im Dateisystem des Geräts vorab zu füllen.

Mit einem App-Asset vorausfüllen

Wenn Sie eine Raumdatenbank vorab mit einer vorkonfigurierten Datenbankdatei füllen möchten, die sich an einer beliebigen Stelle im assets/-Verzeichnis Ihrer Anwendung befindet, rufen Sie die Methode createFromAsset() über Ihr RoomDatabase.Builder-Objekt auf, bevor Sie build() aufrufen:

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();

Die Methode createFromAsset() akzeptiert ein Stringargument, das einen relativen Pfad vom Verzeichnis assets/ zur vorkonfigurierten Datenbankdatei enthält.

Mit Dateisystem vorausfüllen

Wenn Sie eine Room-Datenbank vorab mit einer vorkonfigurierten Datenbankdatei füllen möchten, die sich im Dateisystem des Geräts außer dem assets/-Verzeichnis Ihrer App befindet, rufen Sie die Methode createFromFile() in Ihrem RoomDatabase.Builder-Objekt auf, bevor Sie build() aufrufen:

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();

Die Methode createFromFile() akzeptiert ein Argument File für die vorkonfigurierte Datenbankdatei. In Room wird eine Kopie der angegebenen Datei erstellt, anstatt sie direkt zu öffnen. Achten Sie daher darauf, dass Ihre App Leseberechtigungen für die Datei hat.

Migrationen mit vorkonfigurierten Datenbanken verarbeiten

Vorkonfigurierte Datenbankdateien können auch die Art und Weise ändern, wie Ihre Raumdatenbank Fallback-Migrationen handhabt. Wenn destruktive Migrationen aktiviert sind und Room eine Migration ohne Migrationspfad ausführen muss, löscht Room normalerweise alle Tabellen in der Datenbank und erstellt eine leere Datenbank mit dem angegebenen Schema für die Zielversion. Wenn Sie jedoch eine vorkonfigurierte Datenbankdatei mit derselben Nummer wie die Zielversion hinzufügen, versucht Room, die neu erstellte Datenbank nach der destruktiven Migration mit dem Inhalt der vorgefertigten Datenbankdatei zu füllen.

Weitere Informationen zu Raumdatenbankmigrationen finden Sie unter Raumdatenbanken migrieren.

In den folgenden Abschnitten finden Sie einige Beispiele dafür, wie dies in der Praxis funktioniert.

Beispiel: Fallback-Migration mit einer vorkonfigurierten Datenbank

Angenommen,

  • Ihre App definiert eine Raumdatenbank in Version 3.
  • Die Datenbankinstanz, die bereits auf dem Gerät installiert ist, hat Version 2.
  • Es gibt eine vorkonfigurierte Datenbankdatei in Version 3.
  • Es gibt keinen implementierten Migrationspfad von Version 2 zu Version 3.
  • Destruktive Migrationen sind aktiviert.

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();

Das passiert in dieser Situation:

  1. Da sich die in Ihrer Anwendung definierte Datenbank in Version 3 und die bereits auf dem Gerät installierte Datenbankinstanz in Version 2 befindet, ist eine Migration erforderlich.
  2. Da es keinen implementierten Migrationsplan von Version 2 zu Version 3 gibt, ist die Migration eine Fallback-Migration.
  3. Da die Builder-Methode fallbackToDestructiveMigration() aufgerufen wird, ist die Fallback-Migration destruktiv. Die auf dem Gerät installierte Datenbankinstanz wird vom Room gelöscht.
  4. Da es eine vorkonfigurierte Datenbankdatei in Version 3 gibt, erstellt Room die Datenbank neu und füllt sie mit dem Inhalt der vorkonfigurierten Datenbankdatei. Befindet sich hingegen die vorkonfigurierte Datenbankdatei in Version 2, würde Room darauf hinweisen, dass sie nicht mit der Zielversion übereinstimmt, und sie nicht als Teil der Fallback-Migration verwenden.

Beispiel: Implementierung der Migration mit einer vorkonfigurierten Datenbank

Angenommen, Ihre Anwendung implementiert einen Migrationspfad von Version 2 zu Version 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();

Das passiert in dieser Situation:

  1. Da sich die in Ihrer Anwendung definierte Datenbank in Version 3 und die bereits auf dem Gerät installierte Datenbank in Version 2 befindet, ist eine Migration erforderlich.
  2. Da es einen Migrationspfad von Version 2 zu Version 3 gibt, führt Room die definierte Methode migrate() aus, um die Datenbankinstanz auf dem Gerät auf Version 3 zu aktualisieren und so die Daten beizubehalten, die sich bereits in der Datenbank befinden. Room verwendet nicht die vorkonfigurierte Datenbankdatei, da Room diese Dateien nur im Fall einer Fallback-Migration verwendet.

Beispiel: Mehrstufige Migration mit einer vorkonfigurierten Datenbank

Auch vorgefertigte Datenbankdateien können sich auf Migrationen auswirken, die aus mehreren Schritten bestehen. Betrachten Sie den folgenden Fall:

  • Ihre App definiert eine Raumdatenbank in Version 4.
  • Die Datenbankinstanz, die bereits auf dem Gerät installiert ist, hat Version 2.
  • Es gibt eine vorkonfigurierte Datenbankdatei in Version 3.
  • Es gibt einen implementierten Migrationspfad von Version 3 zu Version 4, aber nicht von Version 2 zu Version 3.
  • Destruktive Migrationen sind aktiviert.

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();

Das passiert in dieser Situation:

  1. Da sich die in Ihrer Anwendung definierte Datenbank in Version 4 und die bereits auf dem Gerät installierte Datenbankinstanz in Version 2 befindet, ist eine Migration erforderlich.
  2. Da es keinen implementierten Migrationspfad von Version 2 zu Version 3 gibt, ist die Migration eine Fallback-Migration.
  3. Da die Builder-Methode fallbackToDestructiveMigration() aufgerufen wird, ist die Fallback-Migration destruktiv. Room löscht die Datenbankinstanz auf dem Gerät.
  4. Da es eine vorkonfigurierte Datenbankdatei in Version 3 gibt, erstellt Room die Datenbank neu und füllt sie mit dem Inhalt der vorkonfigurierten Datenbankdatei.
  5. Die auf dem Gerät installierte Datenbank verwendet jetzt Version 3. Da diese immer noch niedriger als die in Ihrer Anwendung definierte Version ist, ist eine weitere Migration erforderlich.
  6. Da es einen Migrationspfad von Version 3 zu Version 4 gibt, führt Room die definierte Methode migrate() aus, um die Datenbankinstanz auf dem Gerät auf Version 4 zu aktualisieren und dabei die Daten beizubehalten, die aus der vorkonfigurierten Datenbankdatei der Version 3 kopiert wurden.

Weitere Informationen

Weitere Informationen zum Vorabausfüllen einer Raumdatenbank finden Sie in den folgenden zusätzlichen Ressourcen.

Videos

Blogs