La salle ne peut pas vérifier l'intégrité des données

93

J'obtiens cette erreur lors de l'exécution du programme avec la base de données de salle

Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. 
You can simply fix this by increasing the version number.

Il semble que nous ayons besoin de mettre à jour la version de la base de données, mais d'où pouvons-nous le faire dans Room?

Ravi
la source
2
Si vous ne vous souciez pas des données de l'application, la suppression de tout le contenu des paramètres de l'application peut également aider, car elle détruit simplement toute la base de données
O-9

Réponses:

131

Lorsque vous rencontrerez ce message pour la première fois, vous travaillerez probablement sur une version non publiée de la base de données. Si tel est le cas, vous ne devriez probablement pas incrémenter la version de la base de données . Effacer simplement les données de l'application vous fera passer l'exception.

Si vous n'incrémentez pas la base de données (recommandé):

Vous devez effacer les données d'application de l'application des paramètres Android. Vous pouvez également désinstaller la version précédente de l'application, puis installer la nouvelle version pour faire passer l'exception. Cette dernière approche ne fonctionne pas dans certaines conditions (par exemple lorsque l'autorisation de sauvegarde est activée)

Étant donné que la suppression des données d'application fonctionne toujours, j'emprunte cette voie à chaque fois.

Si vous incrémentez la version de la base de données:

Vous devrez écrire le code de migration de la base de données pour prendre en compte les modifications apportées au schéma de base de données. Voir ici pour plus d' informations sur la migration.

Une alternative à l'écriture du code de migration de base de données consiste à faire appel fallbackToDestructiveMigrationau générateur de base de données Room. Ce n'est probablement pas une bonne idée. Oublier de supprimer cet appel, puis oublier de mettre à niveau la base de données entraînera une perte de données.

// Using this fallback is almost certainly a bad idea
Database database = Room.databaseBuilder(context, Database.class, DATABASE_NAME)
        .fallbackToDestructiveMigration()
        .build();

Encore une fois, ni l'incrémentation de la version de la base de données ni le retour à une migration destructive ne sont nécessaires si le schéma de base de données précédent n'est pas vivant dans la nature .

méthode signature
la source
4
Je souhaite qu'ils incluent une autre méthode de secours pour ce cas :(
BoD
3
Dans la version 1.0.0-rc1de Room, la seule chose qui fonctionnait pour moi était d'incrémenter la version de la base de données.
Dick Lucas
42
J'avais android: allowBackup = "true" dans mon AndroidManifest.xml, ce qui empêchait l'effacement des données même après la désinstallation de l'application. J'ai défini cet attribut sur false, puis j'ai réinstallé l'application, ce qui a aidé à résoudre le problème. Notez que true est la valeur par défaut de allowBackup, donc si vous ne l'utilisez pas du tout, il se peut que les données soient toujours conservées.
Bartek
1
@Bartek ce commentaire mérite désormais d'être une réponse.
guness le
Une telle explication! Je désinstallais l'application encore et encore car pourquoi mettre à niveau la version en cours de développement? Oh garçon, je n'ai jamais pensé que la suppression des données des paramètres était la clé pour avancer. Bonne réponse. Devrait être la solution acceptée.
sud007
29

Par défaut, le manifeste Android a android:allowBackup="true", qui permet aux applications de conserver leur base de données SQLite lors de la réinstallation.

Supposons que vous DATABASE_VERSIONaviez initialement 3 ans, puis que vous décidiez de réduire la version DB de 3 à 1.

@Database(entities = {CallRecording.class}, version = DATABASE_VERSION)
public abstract class AppDatabase extends RoomDatabase {
    public abstract RecordingDAO recordingDAO();

//    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
//        @Override
//        public void migrate(SupportSQLiteDatabase database) {
//            // Since we didn't alter the table, there's nothing else to do here.
//        }
//    };
}

Vous pouvez y parvenir comme ça

  • Effacez les données d'application du paramètre. Cela supprimera l'ancienne base de données (DATABASE_VERSION = 3) du téléphone
  • Désinstaller votre application
  • Réduire la version de DATABASE_VERSION à 1
  • Créer et réinstaller votre application

C'est une bonne pratique de rester DATABASE_VERSIONaussi constant.

Hitesh Sahu
la source
1
Cela n'affectera-t-il pas les utilisateurs qui mettront à jour l'application depuis le Play Store?
nimi0112
1
J'ai suivi la même voie, mais je n'ai pas fonctionné. Même si j'essaie d'installer sur un nouvel appareil à partir d'Android Studio, il affiche la même erreur: x
Sadat
@ nimi0112 Pour votre variante de version, vous devez autoriser la sauvegarde, mais pour votre variante de débogage, vous pouvez la désactiver
Chad Mx
25

android: allowBackup = "true" dans AndroidManifest.xml empêche les données d'être effacées même après la désinstallation de l'application.

Ajoutez ceci à votre manifeste:

android:allowBackup="false"

et réinstallez l'application.

Remarque: assurez-vous de rétablir la valeur true ultérieurement si vous souhaitez des sauvegardes automatiques.

Une autre solution:

Vérifiez le identityHash de votre ancien fichier json et le nouveau fichier json dans le dossier apps \ schema.

Si le identityHash est différent, il donnera cette erreur. Découvrez ce que vous avez changé en comparant les deux fichiers json si vous ne voulez rien changer.

Assurez-vous que vous avez exportSchema = true.

@Database(entities = {MyEntity.class, ...}, version = 2, exportSchema = true)

fichier de schéma json:

  "formatVersion": 1,
  "database": {
    "version": 2,
    "identityHash": "53cc5ef34d2ebd33c8518d79d27ed012",
    "entities": [
      {

code:

private void checkIdentity(SupportSQLiteDatabase db) {
    String identityHash = null;
    if (hasRoomMasterTable(db)) {
        Cursor cursor = db.query(new SimpleSQLiteQuery(RoomMasterTable.READ_QUERY));
        //noinspection TryFinallyCanBeTryWithResources
        try {
            if (cursor.moveToFirst()) {
                identityHash = cursor.getString(0);
            }
        } finally {
            cursor.close();
        }
    }
    if (!mIdentityHash.equals(identityHash) && !mLegacyHash.equals(identityHash)) {
        throw new IllegalStateException("Room cannot verify the data integrity. Looks like"
                + " you've changed schema but forgot to update the version number. You can"
                + " simply fix this by increasing the version number.");
    }
}
l'amour en direct
la source
20

La réponse d' Aniruddh Parihar m'a donné un indice et cela s'est résolu.

Recherchez une classe dans laquelle vous avez prolongé RoomDatabase. Vous y trouverez une version comme ci-dessous:

@Database(entities = {YourEntity.class}, version = 1)

augmentez simplement la version et le problème est résolu.

Ravi
la source
11

C'est très simple comme indiqué dans le journal

Looks like you've changed schema but forgot to update the Database version number. 
You can simply fix this by increasing the version number.

Accédez simplement à votre classe de version de base de données et mettez à niveau votre version de base de données en augmentant 1 par rapport à la version actuelle.

Par exemple: recherchez l'annotation @Database dans votre projet comme ci-dessous

@Database(entities = {YourEntityName.class}, version = 1)

Ici, la version = 1, est la version de la base de données, vous devez simplement l'augmenter d'un, c'est tout.

Aniruddh Parihar
la source
1
Oui, j'ai eu cette erreur, c'est pourquoi j'ai également mentionné cela en question It seems we need to update database version. Mais je ne savais pas où cette version était mentionnée. En tout cas merci pour cet indice.
Ravi
Vous avez reformulé le message d'erreur, mais vous n'avez fourni aucune information supplémentaire pour remédier à la confusion de l'auteur d'origine.
Carl Rossman il y a
@CarlRossman: Vous devez trouver votre classe de base de données dans votre projet où vous avez utilisé l'annotation de base de données, sur cette classe, vous trouverez la version de la base de données (valeur entière), augmentez-la simplement d'un à partir de l'actuelle.
Aniruddh Parihar il y a
7

1: - Il semble que nous devions mettre à jour la version de la base de données (incrémenter de 1)

entrez la description de l'image ici

2ème Désinstaller l'application ou Effacer les données de l'application

Keshav Gera
la source
6

Sur un téléphone Android:

Désinstaller l'application ou effacer les données de l'application

Pour supprimer les données de l'application: Allez dans Paramètres -> Applications -> Sélectionnez votre application -> Stockage -> Effacer les données

La désinstallation (et la réinstallation) ne fonctionnent pas dans tous les cas, alors essayez d'abord d'effacer les données!

Marci
la source
Oui cela a fonctionné. Mais étrangement, je recevais ce problème sur un appareil qui a été complètement effacé et configuré à l'instant. Mais simplement effacer les données résolues.
Ajith Memana
Cela ne devrait pas être fait en production. Vous ne devez pas forcer tous vos utilisateurs à effacer les données de l'application. Mieux vaut écrire le code de migration en augmentant la version de 1 dans votre base de données Room.
Rajeev Jayaswal le
5

Dans mon cas, android:allowBackup="false"passer de vrai à faux a fonctionné, car cela m'a déjà donné des cauchemars auparavant, c'est la chose la plus étrange pourquoi ce paramètre est activé par défaut!

Divyanshu Negi
la source
5

Afin de résoudre le problème dans kotlin:

Première

@Database(entities = [Contact::class], version = 2)

Seconde

val MIGRATION_1_2 = object : Migration(1, 2) {
        override fun migrate(database: SupportSQLiteDatabase) {
            database.execSQL("ALTER TABLE Contact ADD COLUMN seller_id TEXT NOT NULL DEFAULT ''")
        }
    }

Troisième

private fun buildDatabase(context: Context) = Room.databaseBuilder(
            context.applicationContext,
            EpayDatabase::class.java,
            "epay"
        )
            .addMigrations(MIGRATION_1_2)
            .build()

Pour plus de détails, consultez la documentation officielle

peterzinho16
la source
4

Ce problème se produit principalement lors du développement.

Si vous changez votre schéma, renommez / ajoutez / modifiez votre classe contenant l'entité de table, l'intégrité entre la sortie de la base de données dans votre construction précédente est en conflit avec la nouvelle construction.

effacez les données de l'application ou installez une nouvelle version après avoir désinstallé la version précédente .

Maintenant, l'ancienne base de données ne sera pas en conflit avec la plus récente.

Extremis II
la source
Après cela, il y a toujours un plantage
user7856586
quelle est l'exception? veuillez mettre le journal pour affiner le problème.
Extremis II
2
Merci, tout va bien maintenant. Je l'ai lu android:allowBackup="true"et l'utilise à bon escient
user7856586
1
@ user7856586 Alors qu'en est-il de allowBackup? Pourriez-vous s'il vous plaît nous éclairer avec votre sagesse?
Ridcully
@Ridcully, vous pouvez en savoir plus ici Pourquoi êtes-vous si en colère?
user7856586
3

Dans mon cas, j'avais une classe AppDatabase.

@Database(entities = {GenreData.class, MoodData.class, SongInfo.class,
    AlbumsInfo.class, UserFolderListsData.class, UserPlaylistResponse.PlayLists.class, InternetConnectionModel.class}, version = 3, exportSchema = false)

J'ai mis à jour ce numéro de version et cela a résolu le problème. Le problème est survenu parce que j'avais ajouté une propriété dans la classe SongInfo et que j'avais oublié de mettre à jour le numéro de version.

J'espère que ça aide quelqu'un.

Harry .Naeem
la source
2

Si vous mettez à niveau la version de Room vers 1.0.0-alpha9 à partir de l'ancienne version, veuillez consulter l'article ci-dessous. Très bon article pour migrer de l'ancienne version vers la version 1.0.0-alpha9.

https://medium.com/@manuelvicnt/android-room-upgrading-alpha-versions-needs-a-migration-with-kotlin-or-nonnull-7a2d140f05b9

In Room Nouvelle version 1.0.0-alpha9 Room ajoute la prise en charge de la contrainte NOT NULL.

Cela va changer le schéma généré par Room. Comme il modifie le schéma, il modifie également le identityHash de la base de données et qui est utilisé par Room pour identifier de manière unique chaque version de la base de données. Par conséquent, nous avons besoin d'une migration

Bhargav Pandya
la source
2

Dans mon cas, ContentProvider et la base de données de la salle fonctionnent ensemble, alors supprimez d'abord tous les rappels de ContentProvider dans toute l'application avec la classe de base de données qui étend la classe SqlLiteOpenHelper

chaman
la source
2

Dans mon cas, j'utilisais une transaction dans la migration et Room n'a pas pu mettre à jour le hachage à l'aide d'un assistant de migration

@get:Rule
val migrationTestHelper: MigrationTestHelper =

MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
                C2GDatabase::class.java.canonicalName,
                FrameworkSQLiteOpenHelperFactory()) 
/* Testing method throws error*/
db = migrationTestHelper.runMigrationsAndValidate(C2GDatabase.DB_NAME,
            3,
            false,
            C2GDatabase.Migration_1_2(),
            C2GDatabase.Migration_2_3())


override fun migrate(database: SupportSQLiteDatabase) {

/** 
    Error
    database.beginTransaction()
**/
database.execSQL("PRAGMA foreign_keys=off;")
database.execSQL("ALTER TABLE user RENAME TO user_old;")
database.execSQL("CREATE TABLE user ( id_user INTEGER PRIMARY KEY AUTOINCREMENT, external_id INTEGER NOT NULL;")
database.execSQL("INSERT INTO user ( id_user, external_id ) " +
                        " SELECT               id_user, external_id" +  
                        " FROM                 user_old;")

database.execSQL("CREATE UNIQUE INDEX idx_unique_user ON user (external_id);")
database.execSQL("PRAGMA foreign_keys=on;")
database.execSQL("DROP TABLE user_old;")
//database.endTransaction() 
}
JARP
la source
J'ai du mal pendant plusieurs heures et c'était la solution !! Merci!!
Javier
1
Dans l'exemple ci-dessus, ce n'est pas la transaction qui pose problème. Vous avez oublié de définir la transaction réussie avant de la terminer: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </code> </pre>
birukoff
2
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

Modifiez le numéro de version dans votre classe RoomDatabase. Incrémentez le numéro de version.

Rajeev Shetty
la source
2

Si l'augmentation de la version du schéma n'a pas fonctionné avec vous, fournissez la migration de votre base de données. Pour ce faire, vous devez déclarer la migration dans le générateur de base de données:

Room.databaseBuilder(context, RepoDatabase.class, DB_NAME)
  .addMigrations(FROM_1_TO_2)
.build();

static final Migration FROM_1_TO_2 = new Migration(1, 2) {
@Override
public void migrate(final SupportSQLiteDatabase database) {
    database.execSQL("ALTER TABLE Repo 
                     ADD COLUMN createdAt TEXT");
    }
};
Agar Magdy
la source
Oui, c'est la bonne voie
Bipin Bharti
1

Je viens d'avoir un problème similaire dans un test d'espresso et la seule chose qui l'a résolu a été la suppression des données et la désinstallation des apks de test androidx comme:

adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services
Daniel Jonker
la source
0

Dans mon cas, je faisais une mise à jour d'une base de données que je préemballerai avec mon application. Aucune des suggestions ici n'a fonctionné. Mais j'ai finalement compris que je pouvais ouvrir le fichier .db dans un programme de base de données (j'ai utilisé "DB Browser for SQLite"), et changer manuellement la "version utilisateur" de 2 à 1. Après cela, cela fonctionnait parfaitement.

Je suppose que toute mise à jour que vous apportez modifie cette version utilisateur, et c'est pourquoi j'ai continué à recevoir cette erreur.

Gavin Wright
la source
Pouvez-vous m'aider avec la même chose? Je ne parviens pas à trouver la version dans DB Browser pour SQLite
GreenROBO
C'est sous l'onglet "Modifier les pragmas". Cela s'appelle "Version utilisateur".
Gavin Wright le
Oui. J? ai compris. Merci pour l'aide Gavin :)
GreenROBO
-1

Dans mon cas, j'ai essayé tout ce qui précède. Rien ne semblait fonctionner, donc la solution pour moi consistait simplement à définir android:allowBackup="false", installer l'application, puis la redéfinir sur true

J'espère que cela aide les autres :)

gmartinsnull
la source
1
C'est exactement ce que j'ai répondu, pourquoi répéter la réponse?
Divyanshu Negi
-2

J'ai eu la même erreur lors du programme de formation de Codelabs. Où Dans une session de formation, j'ai créé un projet et il s'est exécuté avec succès avec toutes les opérations de base de données. Lors de la session suivante, je travaillais avec un dépôt différent, mais c'était une extension du projet précédent.De la première version de l'application étendue, seul j'avais eu l'erreur.

Peut-être que Studio conserve les techniques d'authentification avec la base de données de salle qui manque avec la nouvelle version.

Shrinivas Manjithaya
la source