La salle n'a PAS un bon système de migration, du moins pas avant 2.1.0-alpha03.
Donc, jusqu'à ce que nous ayons un meilleur système de migration, il existe des solutions de contournement pour avoir des migrations faciles dans la salle.
Comme il n'y a pas de méthode telle que @Database(createNewTables = true) ou MigrationSystem.createTable(User::class), qu'il devrait y avoir l'une ou l'autre, la seule façon possible est d'exécuter
CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))
à l'intérieur de votre migrateméthode.
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`))")
}
}
Afin d'obtenir au-dessus du script SQL , vous avez 4 façons
1. Écrivez par vous-même
Fondamentalement, vous devez écrire le script ci-dessus qui correspondra au script généré par Room. Cette manière est possible, pas faisable. (Considérez que vous avez 50 champs)
2. Exporter le schéma
Si vous incluez exportSchema = truedans votre @Databaseannotation, Room générera un schéma de base de données dans / schemas de votre dossier de projet. L'utilisation est
@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
//...
}
Assurez-vous que vous avez inclus les lignes ci-dessous dans build.gradevotre module d'application
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
Lorsque vous exécutez ou générez le projet, vous obtiendrez un fichier JSON contenant 2.jsontoutes les requêtes de votre base de données Room.
"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
},
Ainsi, vous pouvez inclure ce qui précède createSqldans votre migrateméthode.
3. Obtenir une requête depuis AppDatabase_Impl
Si vous ne souhaitez pas exporter le schéma, vous pouvez toujours obtenir la requête en exécutant ou en créant le projet qui générera le AppDatabase_Impl.javafichier. et dans le fichier spécifié, vous pouvez avoir.
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
Dans la createAllTablesméthode, il y aura les scripts de création de toutes les entités. Vous pouvez l'obtenir et l'inclure dans votre migrateméthode.
4. Traitement des annotations.
Comme vous pouvez le deviner, Room génère tous les fichiers mentionnés ci-dessus schemaet les AppDatabase_Implfichiers dans le temps de compilation et avec le traitement d'annotation que vous ajoutez avec
kapt "androidx.room:room-compiler:$room_version"
Cela signifie que vous pouvez également faire de même et créer votre propre bibliothèque de traitement d'annotations qui génère toutes les requêtes de création nécessaires pour vous.
L'idée est de créer une bibliothèque de traitement des annotations pour les annotations de salle de @Entityet @Database. Prenons par exemple une classe annotée @Entity. Voici les étapes que vous devrez suivre
- Créez un nouveau
StringBuilderet ajoutez "CREATE TABLE IF NOT EXISTS"
- Obtenez le nom de la table à partir
class.simplenameou par tableNamechamp de @Entity. Ajoutez-le à votreStringBuilder
- Ensuite, pour chaque champ de votre classe, créez des colonnes de SQL. Prenez le nom, le type, la nullité du champ soit par le champ lui-même, soit par
@ColumnInfoannotation. Pour chaque champ, vous devez ajouter le id INTEGER NOT NULLstyle d'une colonne à votre StringBuilder.
- Ajouter des clés primaires par
@PrimaryKey
- Ajouter
ForeignKeyet Indicess'il existe.
- Après avoir terminé, convertissez-le en chaîne et enregistrez-le dans une nouvelle classe que vous souhaitez utiliser. Par exemple, enregistrez-le comme ci-dessous
public final class UserSqlUtils {
public String createTable = "CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))";
}
Ensuite, vous pouvez l'utiliser comme
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(UserSqlUtils().createTable)
}
}
J'ai créé une telle bibliothèque pour moi-même que vous pouvez consulter et même l'utiliser dans votre projet. Notez que la bibliothèque que j'ai créée n'est pas pleine et qu'elle répond simplement à mes exigences pour la création de table.
RoomExtension pour une meilleure migration
Application qui utilise RoomExtension
J'espère que c'était utile.
METTRE À JOUR
Au moment d'écrire cette réponse, la version de la salle était 2.1.0-alpha03et quand j'ai envoyé un e-mail aux développeurs, j'ai reçu une réponse de
Il est prévu d'avoir un meilleur système de migration dans 2.2.0
Malheureusement, il nous manque encore un meilleur système de migration.