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 gibt MigrationSystem.createTable(User::class), die es geben sollte, ist der einzig mögliche Weg das Ausführen
CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))
innerhalb Ihrer migrateMethode.
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))")
}
}
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 = truein Ihre @DatabaseAnmerkung aufnehmen, generiert Room ein Datenbankschema in / schemas Ihres Projektordners. Die Verwendung ist
@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
//...
}
Stellen Sie sicher, dass Sie die folgenden Zeilen in build.gradeIhr App-Modul aufgenommen haben
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
Wenn Sie das Projekt ausführen oder erstellen, erhalten Sie eine JSON-Datei 2.json, die alle Abfragen in Ihrer Room-Datenbank enthält.
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "325bd539353db508c5248423a1c88c03",
"entities": [
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
Sie können also das oben createSqlGenannte in Ihre migrateMethode 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.javaerstellen, das eine Datei generiert . und innerhalb der angegebenen Datei, die Sie haben können.
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
Innerhalb der createAllTablesMethode gibt es die Erstellungsskripte aller Entitäten. Sie können es erhalten und in Ihre migrateMethode einbeziehen.
4. Anmerkungsverarbeitung.
Wie Sie sich vorstellen können, generiert Room alle oben genannten Dateien schemaund AppDatabase_ImplDateien innerhalb der Kompilierungszeit und mit der von Ihnen hinzugefügten Anmerkungsverarbeitung
kapt "androidx.room:room-compiler:$room_version"
Das 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 @Entityund zu erstellen @Database. Nehmen Sie eine Klasse, die @Entityzum Beispiel mit Anmerkungen versehen ist . Dies sind die Schritte, denen Sie folgen müssen
StringBuilderErstellen Sie eine neue und fügen Sie "TABELLE ERSTELLEN, WENN NICHT EXISTIERT" hinzu.
- Holen Sie sich den Tabellennamen entweder aus
class.simplenameoder nach tableNameFeld von @Entity. Fügen Sie es Ihrem hinzuStringBuilder
- Erstellen Sie dann für jedes Feld Ihrer Klasse SQL-Spalten. Nehmen Sie den Namen, den Typ und die Nullfähigkeit des Feldes entweder durch das Feld selbst oder durch
@ColumnInfoAnmerkungen. Für jedes Feld müssen Sie id INTEGER NOT NULLIhren Spaltenstil hinzufügen StringBuilder.
- Primärschlüssel hinzufügen durch
@PrimaryKey
- Hinzufügen
ForeignKeyund Indicesfalls vorhanden.
- Konvertieren Sie es nach Abschluss in einen String und speichern Sie es in einer neuen Klasse, die Sie verwenden möchten. Speichern Sie es beispielsweise wie unten beschrieben
public final class UserSqlUtils {
public String createTable = "CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))";
}
Dann können Sie es als verwenden
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(UserSqlUtils().createTable)
}
}
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-alpha03Raumversion und als ich Entwicklern eine E-Mail schickte, erhielt ich eine Antwort von
Es wird erwartet, dass es ein besseres Migrationssystem gibt 2.2.0
Leider fehlt uns immer noch ein besseres Migrationssystem.