Nehmen wir nicht an, ich habe eine einfache Raumdatenbank:
@Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Jetzt füge ich eine neue Entität hinzu: Pet
und stoße Version auf 2:
@Database(entities = {User.class, Pet.class}, version = 2)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Natürlich wirft Room eine Ausnahme: java.lang.IllegalStateException: A migration from 1 to 2 is necessary.
Angenommen, ich habe die User
Klasse nicht geändert (damit alle Daten sicher sind), muss ich eine Migration bereitstellen, die nur eine neue Tabelle erstellt. Ich untersuche also Klassen, die von Room generiert wurden, suche nach generierten Abfragen, um meine neue Tabelle zu erstellen, kopiere sie und füge sie in die Migration ein:
final Migration MIGRATION_1_2 =
new Migration(1, 2) {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `Pet` (`name` TEXT NOT NULL, PRIMARY KEY(`name`))");
}
};
Ich finde es jedoch unpraktisch, es manuell zu tun. Gibt es eine Möglichkeit, Room zu sagen: Ich berühre keine der vorhandenen Tabellen, daher sind Daten sicher. Bitte erstellen Sie eine Migration für mich?
quelle
Antworten:
Der Raum hat KEIN gutes Migrationssystem, zumindest nicht bis
2.1.0-alpha03
.Bis wir ein besseres Migrationssystem haben, gibt es einige Problemumgehungen für einfache Migrationen im Raum.
Da es keine Methode wie
@Database(createNewTables = true)
oder gibtMigrationSystem.createTable(User::class)
, die es geben sollte, ist der einzig mögliche Weg das Ausführeninnerhalb Ihrer
migrate
Methode.Um über das SQL- Skript hinauszukommen , haben Sie vier Möglichkeiten
1. Schreiben Sie selbst
Grundsätzlich müssen Sie das obige Skript schreiben, das mit dem von Room generierten Skript übereinstimmt. Dieser Weg ist möglich, nicht machbar. (Angenommen, Sie haben 50 Felder)
2. Schema exportieren
Wenn Sie
exportSchema = true
in Ihre@Database
Anmerkung aufnehmen, generiert Room ein Datenbankschema in / schemas Ihres Projektordners. Die Verwendung istStellen Sie sicher, dass Sie die folgenden Zeilen in
build.grade
Ihr App-Modul aufgenommen habenWenn Sie das Projekt ausführen oder erstellen, erhalten Sie eine JSON-Datei
2.json
, die alle Abfragen in Ihrer Room-Datenbank enthält.Sie können also das oben
createSql
Genannte in Ihremigrate
Methode aufnehmen.3. Abfrage von AppDatabase_Impl abrufen
Wenn Sie kein Schema exportieren möchten, können Sie die Abfrage trotzdem abrufen, indem Sie das Projekt ausführen oder
AppDatabase_Impl.java
erstellen, das eine Datei generiert . und innerhalb der angegebenen Datei, die Sie haben können.Innerhalb der
createAllTables
Methode gibt es die Erstellungsskripte aller Entitäten. Sie können es erhalten und in Ihremigrate
Methode einbeziehen.4. Anmerkungsverarbeitung.
Wie Sie sich vorstellen können, generiert Room alle oben genannten Dateien
schema
undAppDatabase_Impl
Dateien innerhalb der Kompilierungszeit und mit der von Ihnen hinzugefügten AnmerkungsverarbeitungDas heißt, Sie können auch das Gleiche tun und eine eigene Bibliothek zur Verarbeitung von Anmerkungen erstellen, die alle erforderlichen Erstellungsabfragen für Sie generiert.
Die Idee ist, eine Bibliothek zur Verarbeitung von Anmerkungen für Raumanmerkungen von
@Entity
und zu erstellen@Database
. Nehmen Sie eine Klasse, die@Entity
zum Beispiel mit Anmerkungen versehen ist . Dies sind die Schritte, denen Sie folgen müssenStringBuilder
Erstellen Sie eine neue und fügen Sie "TABELLE ERSTELLEN, WENN NICHT EXISTIERT" hinzu.class.simplename
oder nachtableName
Feld von@Entity
. Fügen Sie es Ihrem hinzuStringBuilder
@ColumnInfo
Anmerkungen. Für jedes Feld müssen Sieid INTEGER NOT NULL
Ihren Spaltenstil hinzufügenStringBuilder
.@PrimaryKey
ForeignKey
undIndices
falls vorhanden.Dann können Sie es als verwenden
Ich habe mir eine solche Bibliothek erstellt, die Sie auschecken und sogar in Ihrem Projekt verwenden können. Beachten Sie, dass die von mir erstellte Bibliothek nicht voll ist und nur meine Anforderungen für die Tabellenerstellung erfüllt.
RoomExtension für eine bessere Migration
Anwendung, die RoomExtension verwendet
Hoffe es war nützlich.
AKTUALISIEREN
Zum Zeitpunkt des Schreibens dieser Antwort war die
2.1.0-alpha03
Raumversion und als ich Entwicklern eine E-Mail schickte, erhielt ich eine Antwort vonLeider fehlt uns immer noch ein besseres Migrationssystem.
quelle
Leider unterstützt Room die automatische Erstellung von Tabellen ohne Datenverlust nicht.
Es ist obligatorisch, die Migration zu schreiben. Andernfalls werden alle Daten gelöscht und die neue Tabellenstruktur erstellt.
quelle
Sie können dies tun-
Der Rest ist derselbe wie oben erwähnt.
Referenz - Für mehr
quelle
Sie können den folgenden Gradle-Befehl zu Ihrer defaultConfig in Ihrer app.gradle hinzufügen:
Wenn Sie dies ausführen, wird eine Liste von Tabellennamen mit den entsprechenden CREATE TABLE-Anweisungen erstellt, aus denen Sie sie einfach kopieren und in Ihre Migrationsobjekte einfügen können. Möglicherweise müssen Sie die Tabellennamen ändern.
Dies stammt beispielsweise aus meinem generierten Schema:
Also kopiere ich, füge die createSql-Anweisung ein und ändere '$ {TABLE_NAME}' in 'Assets', den Tabellennamen, und voila automatisch generierte Room-Create-Anweisungen.
quelle
In diesem Fall müssen Sie keine Migration durchführen. Sie können .fallbackToDestructiveMigration () aufrufen, wenn Sie eine Datenbankinstanz erstellen.
Beispiel:
Und vergessen Sie nicht, die Datenbankversion zu ändern.
quelle
Vielleicht können Sie in diesem Fall (wenn Sie nur eine neue Tabelle erstellt haben, ohne andere zu ändern) dies tun, ohne Migrationen zu erstellen?
quelle