Ne supposons pas, j'ai une base de données de salle simple:
@Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Maintenant, j'ajoute une nouvelle entité: Pet
et passe la version à 2:
@Database(entities = {User.class, Pet.class}, version = 2)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Bien sûr, Room lève une exception: java.lang.IllegalStateException: A migration from 1 to 2 is necessary.
En supposant que je n'ai pas changé de User
classe (donc toutes les données sont en sécurité), je dois fournir une migration qui crée simplement une nouvelle table. Donc, je regarde dans les classes générées par Room, je recherche la requête générée pour créer ma nouvelle table, je la copie et la colle dans la migration:
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`))");
}
};
Cependant, je trouve peu pratique de le faire manuellement. Existe-t-il un moyen de dire à Room: Je ne touche à aucune table existante, donc les données sont en sécurité. Veuillez créer une migration pour moi?
la source
Réponses:
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)
ouMigrationSystem.createTable(User::class)
, qu'il devrait y avoir l'une ou l'autre, la seule façon possible est d'exécuterà l'intérieur de votre
migrate
méthode.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 = true
dans votre@Database
annotation, Room générera un schéma de base de données dans / schemas de votre dossier de projet. L'utilisation estAssurez-vous que vous avez inclus les lignes ci-dessous dans
build.grade
votre module d'applicationLorsque vous exécutez ou générez le projet, vous obtiendrez un fichier JSON contenant
2.json
toutes les requêtes de votre base de données Room.Ainsi, vous pouvez inclure ce qui précède
createSql
dans votremigrate
mé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.java
fichier. et dans le fichier spécifié, vous pouvez avoir.Dans la
createAllTables
méthode, il y aura les scripts de création de toutes les entités. Vous pouvez l'obtenir et l'inclure dans votremigrate
méthode.4. Traitement des annotations.
Comme vous pouvez le deviner, Room génère tous les fichiers mentionnés ci-dessus
schema
et lesAppDatabase_Impl
fichiers dans le temps de compilation et avec le traitement d'annotation que vous ajoutez avecCela 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
@Entity
et@Database
. Prenons par exemple une classe annotée@Entity
. Voici les étapes que vous devrez suivreStringBuilder
et ajoutez "CREATE TABLE IF NOT EXISTS"class.simplename
ou partableName
champ de@Entity
. Ajoutez-le à votreStringBuilder
@ColumnInfo
annotation. Pour chaque champ, vous devez ajouter leid INTEGER NOT NULL
style d'une colonne à votreStringBuilder
.@PrimaryKey
ForeignKey
etIndices
s'il existe.Ensuite, vous pouvez l'utiliser comme
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-alpha03
et quand j'ai envoyé un e-mail aux développeurs, j'ai reçu une réponse deMalheureusement, il nous manque encore un meilleur système de migration.
la source
Désolé, Room ne prend pas en charge la création automatique de tables sans perte de données.
Il est obligatoire d'écrire la migration. Sinon, cela effacera toutes les données et créera la nouvelle structure de table.
la source
Vous pouvez faire de cette façon-
Le reste sera le même que celui que vous avez mentionné ci-dessus-
Référence - Pour en savoir plus
la source
Vous pouvez ajouter la commande gradle suivante à votre defaultConfig dans votre app.gradle:
Lorsque vous l'exécutez, il compilera une liste de noms de table avec leurs instructions CREATE TABLE pertinentes à partir de laquelle vous pourrez simplement copier et coller dans vos objets de migration. Vous devrez peut-être changer les noms de table.
Par exemple, cela provient de mon schéma généré:
Et donc, je copie, collez l'instruction createSql et changez le '$ {TABLE_NAME}' en 'assets' le nom de la table, et voilà les instructions de création de salle générées automatiquement.
la source
Dans ce cas, vous n'avez pas besoin d'effectuer une migration, vous pouvez appeler .fallbackToDestructiveMigration () lorsque vous créez une instance de base de données.
Exemple:
Et n'oubliez pas de changer la version de la base de données.
la source
Peut-être que dans ce cas (si vous avez seulement créé une nouvelle table sans en changer d'autres), vous pouvez le faire sans créer de migrations du tout?
la source