Room kann die Datenintegrität nicht überprüfen

101

Ich erhalte diesen Fehler, wenn ich ein Programm mit Room Database ausführe

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.

Es scheint, dass wir die Datenbankversion aktualisieren müssen, aber von wo aus können wir das in Room tun?

Ravi
quelle
2
Wenn Sie sich nicht um die Daten der App kümmern, kann das Löschen aller Inhalte aus den Anwendungseinstellungen ebenfalls hilfreich sein, da dadurch nur die gesamte
O-9

Antworten:

137

Wenn Sie zum ersten Mal auf diese Nachricht stoßen, arbeiten Sie höchstwahrscheinlich gegen eine unveröffentlichte Version der Datenbank. In diesem Fall sollten Sie die Datenbankversion höchstwahrscheinlich nicht erhöhen . Durch einfaches Löschen der App-Daten haben Sie die Ausnahme bestanden.

Wenn Sie die Datenbank nicht erhöhen (empfohlen):

Sie sollten die App-Daten der Anwendung aus den Android-Einstellungen löschen. Alternativ können Sie möglicherweise die vorherige App-Version deinstallieren und dann die neue Version installieren, um die Ausnahme zu übergeben. Dieser letztere Ansatz funktioniert unter bestimmten Bedingungen nicht (z. B. wenn die Option "Sicherung zulassen" aktiviert ist).

Da das Löschen von Anwendungsdaten immer funktioniert, gehe ich jedes Mal diesen Weg.

Wenn Sie die Datenbankversion erhöhen:

Sie müssen Datenbankmigrationscode schreiben, um Änderungen am Datenbankschema zu berücksichtigen. Sehen Sie hier für Informationen zu Migration.

Alternativ zum Schreiben des Datenbankmigrationscodes können Sie fallbackToDestructiveMigrationden Room Database Builder aufrufen . Dies ist wahrscheinlich keine gute Idee. Wenn Sie vergessen, diesen Aufruf zu entfernen und dann die Datenbank zu aktualisieren, gehen Daten verloren.

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

Auch hier ist weder ein Inkrementieren der Datenbankversion noch ein Zurückgreifen auf eine destruktive Migration erforderlich, wenn das vorherige Datenbankschema nicht in freier Wildbahn ausgeführt wird .

Methodensignatur
quelle
4
Ich wünschte, sie würden eine andere Fallback-Methode für diesen Fall enthalten :(
BoD
3
In der Version 1.0.0-rc1von Room war das einzige, was für mich funktioniert hat, die Datenbankversion zu erhöhen.
Dick Lucas
42
Ich hatte android: allowBackup = "true" in meiner AndroidManifest.xml, wodurch verhindert wurde, dass die Daten auch nach der Deinstallation der App gelöscht wurden. Ich habe dieses Attribut auf false gesetzt und dann die App neu installiert, was dazu beigetragen hat, das Problem zu beheben. Beachten Sie, dass true der Standardwert für allowBackup ist. Wenn Sie ihn also überhaupt nicht verwenden, werden die Daten möglicherweise weiterhin beibehalten.
Bartek
1
@Bartek Dieser Kommentar verdient jetzt eine Antwort.
Guness
Eine solche Erklärung! Ich habe die App immer wieder deinstalliert, weil ich die Version in der Entwicklung aktualisiere. Oh Mann, hätte nie gedacht, dass das Löschen von Daten aus Einstellungen der Schlüssel ist. Gute Antwort. Sollte die akzeptierte Lösung sein.
Sud007
30

Standardmäßig haben Android-Manifeste android:allowBackup="true", mit denen Apps ihre SQLite-Datenbank bei Neuinstallation beibehalten können.

Angenommen, Sie DATABASE_VERSIONwaren anfangs 3 und dann entscheiden Sie sich, die DB-Version von 3 auf 1 zu reduzieren.

@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.
//        }
//    };
}

Sie können es so erreichen

  • Löschen Sie die App-Daten aus der Einstellung. Dadurch wird die ältere Datenbank (DATABASE_VERSION = 3) vom Telefon entfernt
  • Deinstallieren Sie Ihre App
  • Reduzieren Sie die Version DATABASE_VERSION auf 1
  • Erstellen und installieren Sie Ihre App neu

Es ist eine gute Praxis, DATABASE_VERSIONso konstant wie möglich zu bleiben .

Hitesh Sahu
quelle
1
Betrifft dies nicht die Benutzer, die die App aus dem Play Store aktualisieren?
nimi0112
1
Ich bin den gleichen Weg gegangen, habe aber nicht funktioniert. Sogar ich versuche, auf einem neuen Gerät von Android Studio zu installieren, es zeigt den gleichen Fehler: x
Sadat
@ nimi0112 Für Ihre Release-Variante sollten Sie Backup sichern, aber für Ihre Debug-Variante können Sie es deaktivieren
Chad Mx
26

android: allowBackup = "true" in AndroidManifest.xml verhindert, dass die Daten auch nach der Deinstallation der App gelöscht werden.

Fügen Sie dies Ihrem Manifest hinzu:

android:allowBackup="false"

und installieren Sie die App neu.

Hinweis: Stellen Sie sicher, dass Sie es später wieder auf true ändern, wenn Sie automatische Sicherungen wünschen.

Eine andere Lösung:

Überprüfen Sie den identityHash Ihrer alten json-Datei und der neuen json-Datei im Ordner apps \ schema.

Wenn der identityHash unterschiedlich ist, wird dieser Fehler ausgegeben. Finden Sie heraus, was Sie geändert haben, indem Sie beide JSON-Dateien vergleichen, wenn Sie nichts ändern möchten.

Stellen Sie sicher, dass Sie exportSchema = true haben.

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

JSON-Schemadatei:

  "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.");
    }
}
Live-Liebe
quelle
20

Aniruddh Parihars Antwort gab mir einen Hinweis und es löste sich.

Suchen Sie nach einer Klasse, in der Sie erweitert haben RoomDatabase. Dort finden Sie die folgende Version:

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

Erhöhen Sie einfach die Version und das Problem ist gelöst.

Ravi
quelle
12

Es ist sehr einfach, wie im Protokoll gezeigt

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

Gehen Sie einfach zu Ihrer Datenbankversionsklasse und aktualisieren Sie Ihre DB-Version, indem Sie 1 von der aktuellen erhöhen.

Zum Beispiel: Suchen Sie die @ Database-Annotation in Ihrem Projekt wie unten

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

Hier ist Version = 1, ist Datenbankversion, Sie müssen es nur um eins erhöhen, das ist es.

Aniruddh Parihar
quelle
1
Ja, ich habe diesen Fehler bekommen, deshalb habe ich auch das in Frage gestellt It seems we need to update database version. Aber ich kam nicht dahin, wo diese Version erwähnt wurde. Trotzdem danke für diesen Hinweis.
Ravi
Sie haben die Fehlermeldung umformuliert, aber keine zusätzlichen Informationen bereitgestellt, um die Verwirrung des Originalplakats zu beheben.
Carl Rossman
@CarlRossman: Sie müssen Ihre Datenbankklasse in Ihrem Projekt finden, in dem Sie die Datenbankanmerkung verwendet haben. In dieser Klasse finden Sie die Datenbankversion (ganzzahliger Wert). Erhöhen Sie sie einfach um eins gegenüber dem aktuellen Wert.
Aniruddh Parihar
7

1: - Es scheint, dass wir die Datenbankversion aktualisieren müssen (um 1 erhöhen)

Geben Sie hier die Bildbeschreibung ein

2. Deinstallieren Sie die App oder löschen Sie die App-Daten

Keshav Gera
quelle
6

Auf Android-Handy:

Deinstallieren Sie die App oder löschen Sie die App-Daten

So löschen Sie App-Daten: Gehen Sie zu Einstellungen -> Apps -> Wählen Sie Ihre App aus -> Speicher -> Daten löschen

Die Deinstallation (und Neuinstallation) funktioniert nicht in jedem Fall. Versuchen Sie also zuerst, Daten zu löschen!

Marci
quelle
Ja das hat funktioniert. Aber seltsamerweise bekam ich dieses Problem auf einem Gerät, das komplett gelöscht und gerade neu eingerichtet wurde. Aber einfach die gelösten Daten löschen.
Ajith Memana
Dies sollte nicht in der Produktion erfolgen. Sie sollten nicht alle Benutzer zwingen, Daten aus der App zu löschen. Schreiben Sie besser Migrationscode, indem Sie die Version in Ihrer Room-Datenbank um 1 erhöhen.
Rajeev Jayaswal
5

In meinem Fall android:allowBackup="false"ist es das Seltsamste, warum diese Einstellung standardmäßig aktiviert ist, da dies auch zu Albträumen geführt hat.

Divyanshu Negi
quelle
5

Um das Problem in Kotlin zu beheben:

Zuerst

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

Zweite

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 ''")
        }
    }

Dritte

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

Weitere Informationen finden Sie in der offiziellen Dokumentation

peterzinho16
quelle
4

Dieses Problem tritt hauptsächlich in der Entwicklung auf.

Wenn Sie Ihr Schema ändern, dh Ihre Klasse mit Tabellenentität umbenennen / hinzufügen / ändern, widerspricht die Integrität zwischen dem Beenden von db in Ihrem vorherigen Build einem neuen Build.

Löschen Sie die App-Daten oder installieren Sie einen neuen Build, nachdem Sie den vorherigen Build deinstalliert haben .

Jetzt wird die alte Datenbank nicht mit der neueren in Konflikt geraten.

Extremis II
quelle
Danach ist immer noch Absturz
user7856586
Was ist die Ausnahme? Bitte legen Sie das Protokoll auf, um das Problem einzugrenzen.
Extremis II
2
Danke, jetzt ist alles in Ordnung. Ich habe darüber gelesen android:allowBackup="true"und benutze es mit Bedacht
user7856586
1
@ user7856586 Was ist also mit allowBackup? Könnten Sie uns bitte mit Ihrer Weisheit aufklären?
Ridcully
@Ridcully können Sie das lesen hier , warum Sie so wütend sind?
user7856586
3

In meinem Fall hatte ich eine AppDatabase-Klasse.

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

Ich habe diese Versionsnummer aktualisiert und das Problem behoben. Das Problem trat auf, weil ich eine Eigenschaft in der SongInfo-Klasse hinzugefügt und vergessen hatte, die Versionsnummer zu aktualisieren.

Hoffe es hilft jemandem.

Harry .Naeem
quelle
2

Wenn Sie die Room-Version von der alten Version auf 1.0.0-alpha9 aktualisieren, besuchen Sie bitte den folgenden Artikel. Sehr guter Artikel für die Migration von der alten Version auf die Version 1.0.0-alpha9.

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

In Room New Version 1.0.0-alpha9 bietet Room Unterstützung für die NOT NULL-Einschränkung.

Dadurch wird das von Room generierte Schema geändert. Da es das Schema ändert, ändert es auch den identityHash der Datenbank, der von Room verwendet wird, um jede DB-Version eindeutig zu identifizieren. Deshalb brauchen wir eine Migration

Bhargav Pandya
quelle
2

In meinem Fall arbeiten ContentProvider und Raumdatenbank zusammen. Entfernen Sie daher zunächst alle Rückrufe von ContentProvider in der gesamten Anwendung mit der Datenbankklasse, die die SqlLiteOpenHelper-Klasse erweitert

Chaman
quelle
2

In meinem Fall habe ich eine Transaktion innerhalb der Migration verwendet und Room konnte den Hash nicht mit einem Migrationshelfer aktualisieren

@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
quelle
Ich kämpfe mehrere Stunden und das war die Lösung !! Dankeschön!!
Javier
1
Im obigen Beispiel ist nicht die Transaktion ein Problem. Sie haben vergessen, die Transaktion erfolgreich zu setzen, bevor Sie sie beendet haben: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </ code> </ pre>
birukoff
2
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

Ändern Sie die Versionsnummer in Ihrer RoomDatabase-Klasse. Erhöhen Sie die Versionsnummer.

Rajeev Shetty
quelle
2

Wenn das Erhöhen der Schemaversion bei Ihnen nicht funktioniert hat, stellen Sie die Migration Ihrer Datenbank bereit. Dazu müssen Sie die Migration im Datenbank-Builder deklarieren:

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");
    }
};
Hagar Magdy
quelle
Ja, das ist der richtige Weg
Bipin Bharti
1

Ich hatte gerade ein ähnliches Problem in einem Espresso-Test und das einzige, was es behoben hat, war das Löschen von Daten und auch das Deinstallieren der AndroidX-Test-Apks wie:

adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services
Daniel Jonker
quelle
0

In meinem Fall habe ich ein Update für eine Datenbank vorgenommen, die ich mit meiner App vorverpacken werde. Keiner der Vorschläge hier hat funktioniert. Aber ich habe endlich herausgefunden, dass ich die .db-Datei in einem Datenbankprogramm öffnen kann (ich habe "DB Browser for SQLite" verwendet) und die "Benutzerversion" manuell von 2 zurück auf 1 ändern kann. Danach hat es perfekt funktioniert.

Ich denke, jedes Update, das Sie an dieser Benutzerversion vornehmen, und aus diesem Grund wurde dieser Fehler immer wieder angezeigt.

Gavin Wright
quelle
Kannst du mir dabei helfen? Ich kann die Version im DB Browser für SQLite
GreenROBO
Es befindet sich unter der Registerkarte "Pragmas bearbeiten". Es heißt "User Version".
Gavin Wright
Ja. Ich hab es geschafft. Danke für die Hilfe Gavin :)
GreenROBO
-1

In meinem Fall habe ich alles versucht. Nichts schien zu funktionieren, daher bestand die Lösung für mich darin android:allowBackup="false", die App einfach einzustellen, zu installieren und dann wieder auf true zu setzen

Hoffe es hilft anderen :)

gmartinsnull
quelle
1
Genau das habe ich beantwortet, warum die Antwort wiederholen?
Divyanshu Negi
-2

Ich habe den gleichen Fehler während des Trainingsprogramms von Codelabs erhalten. Wo In einer Schulungssitzung habe ich ein Projekt erstellt, das mit allen Datenbankoperationen erfolgreich ausgeführt wurde. In der nächsten Sitzung arbeitete ich mit einem anderen Repo, aber es war eine Erweiterung des vorherigen Projekts. Vom ersten Build der erweiterten App an hatte nur ich den Fehler erhalten.

Möglicherweise behält Studio Authentifizierungstechniken mit der Raumdatenbank bei, die beim neuen Build fehlt.

Shrinivas Manjithaya
quelle