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 migrate
Methode.
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 = true
in Ihre @Database
Anmerkung 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.grade
Ihr 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 createSql
Genannte in Ihre migrate
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.
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
Innerhalb der createAllTables
Methode gibt es die Erstellungsskripte aller Entitäten. Sie können es erhalten und in Ihre migrate
Methode einbeziehen.
4. Anmerkungsverarbeitung.
Wie Sie sich vorstellen können, generiert Room alle oben genannten Dateien schema
und AppDatabase_Impl
Dateien 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 @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üssen
StringBuilder
Erstellen Sie eine neue und fügen Sie "TABELLE ERSTELLEN, WENN NICHT EXISTIERT" hinzu.
- Holen Sie sich den Tabellennamen entweder aus
class.simplename
oder nach tableName
Feld 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
@ColumnInfo
Anmerkungen. Für jedes Feld müssen Sie id INTEGER NOT NULL
Ihren Spaltenstil hinzufügen StringBuilder
.
- Primärschlüssel hinzufügen durch
@PrimaryKey
- Hinzufügen
ForeignKey
und Indices
falls 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-alpha03
Raumversion 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.