Pokój nie może zweryfikować integralności danych

91

Otrzymuję ten błąd podczas uruchamiania programu z bazą danych pomieszczeń

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.

Wygląda na to, że musimy zaktualizować wersję bazy danych, ale skąd możemy to zrobić w pokoju?

Ravi
źródło
2
Jeśli nie dbasz o dane aplikacji, usunięcie całej zawartości z ustawień aplikacji może również pomóc, ponieważ po prostu niszczy całą bazę danych
O-9

Odpowiedzi:

131

Kiedy po raz pierwszy natrafisz na ten komunikat, najprawdopodobniej będziesz pracować z niewydaną wersją bazy danych. W takim przypadku najprawdopodobniej nie należy zwiększać wersji bazy danych . Po prostu wyczyszczenie danych aplikacji spowoduje przeniesienie wyjątku.

Jeśli nie zwiększasz bazy danych (zalecane):

Należy wyczyścić dane aplikacji z ustawień Androida. Alternatywnie możesz odinstalować poprzednią wersję aplikacji, a następnie zainstalować nową, aby uzyskać wyjątek. To drugie podejście nie działa w pewnych warunkach (np. Gdy włączona jest opcja zezwalania na tworzenie kopii zapasowych)

Ponieważ czyszczenie danych aplikacji zawsze działa, za każdym razem wybieram tę trasę.

Jeśli zwiększysz wersję bazy danych:

Będziesz musiał napisać kod migracji bazy danych, aby uwzględnić wszelkie zmiany w schemacie bazy danych. Zobacz tutaj, aby uzyskać informacje na temat migracji.

Alternatywą dla pisania kodu migracji bazy danych jest wywołanie fallbackToDestructiveMigrationkonstruktora bazy danych Room. To prawdopodobnie nie jest dobry pomysł. Zapomnienie o usunięciu tego wywołania, a następnie zapomnienie o aktualizacji bazy danych spowoduje utratę danych.

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

Ponownie, ani zwiększanie wersji bazy danych, ani cofanie się do destrukcyjnej migracji nie jest konieczne, jeśli poprzedni schemat bazy danych nie istnieje na wolności .

metody podpisu
źródło
4
Chciałbym, żeby w tym przypadku uwzględnili inną metodę awaryjną :(
BoD,
3
W wersji 1.0.0-rc1Room jedyną rzeczą, która działała dla mnie, było zwiększenie wersji bazy danych.
Dick Lucas
42
Miałem androida: allowBackup = "true" w moim AndroidManifest.xml, co uniemożliwiało wyczyszczenie danych nawet po odinstalowaniu aplikacji. Ustawiłem ten atrybut na false, a następnie ponownie zainstalowałem aplikację, co pomogło pozbyć się problemu. Zwróć uwagę, że true jest domyślną wartością parametru allowBackup, więc jeśli w ogóle jej nie używasz, nadal może to spowodować zachowanie danych.
Bartek
1
@Bartek ten komentarz zasługuje teraz na odpowiedź.
broni
Takie wyjaśnienie! Wielokrotnie odinstalowałem aplikację, ponieważ po co aktualizować wersję w fazie rozwoju? O rany, nigdy nie myślałem, że usuwanie danych z ustawień jest kluczem do przodu. Niezła odpowiedź. Powinno być akceptowanym rozwiązaniem.
sud007
29

Domyślnie manifest systemu Android ma android:allowBackup="true", które umożliwiają aplikacjom zachowanie ich bazy danych SQLite podczas ponownej instalacji.

Załóżmy, że DATABASE_VERSIONpoczątkowo miałeś 3, a potem zdecydujesz się zredukować wersję DB z 3 do 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.
//        }
//    };
}

Możesz to osiągnąć w ten sposób

  • Wyczyść dane aplikacji z ustawień. Spowoduje to usunięcie starszej bazy danych (DATABASE_VERSION = 3) z telefonu
  • Odinstaluj swoją aplikację
  • Zmniejsz wersję DATABASE_VERSION do 1
  • Zbuduj i ponownie zainstaluj swoją aplikację

To dobra praktyka, aby zachować DATABASE_VERSIONtaką stałą.

Hitesh Sahu
źródło
1
Czy nie wpłynie to na użytkowników, którzy będą aktualizować aplikację ze sklepu Play?
nimi0112
1
Poszedłem tą samą drogą, ale nie zadziałało. Nawet próbuję zainstalować na nowym urządzeniu z Android Studio, pokazuje ten sam błąd: x
Sadat
@ nimi0112 Dla wariantu wydania powinieneś zezwolić na tworzenie kopii zapasowych, jednak dla wariantu debugowania możesz go wyłączyć
Chad Mx
25

android: allowBackup = "true" w pliku AndroidManifest.xml zapobiega wyczyszczeniu danych nawet po odinstalowaniu aplikacji.

Dodaj to do swojego manifestu:

android:allowBackup="false"

i ponownie zainstaluj aplikację.

Uwaga: pamiętaj, aby później zmienić to z powrotem na true, jeśli chcesz automatycznie tworzyć kopie zapasowe.

Inne rozwiązanie:

Sprawdź tożsamość Hash starego pliku json i nowego pliku json w folderze apps \ schema.

Jeśli tożsamość Hash jest inna, zwróci ten błąd. Dowiedz się, co zmieniłeś, porównując oba pliki json, jeśli nie chcesz niczego zmieniać.

Upewnij się, że masz wartość exportSchema = true.

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

json plik schematu:

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

kod:

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.");
    }
}
miłość na żywo
źródło
19

Odpowiedź Aniruddha Parihara dała mi wskazówkę i rozwiązała.

Wyszukaj klasę, w której przedłużyłeś RoomDatabase. Znajdziesz tam wersję jak poniżej:

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

po prostu zwiększ wersję i problem zostanie rozwiązany.

Ravi
źródło
12

Jego bardzo proste, jak pokazano w dzienniku

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

Po prostu przejdź do klasy wersji bazy danych i zaktualizuj wersję bazy danych, zwiększając o 1 z aktualnej.

Aniruddh Parihar
źródło
1
Tak, dostałem ten błąd, dlatego w pytaniu również o tym wspomniałem It seems we need to update database version. Ale nie rozumiałem, gdzie wspomniano o tej wersji. W każdym razie dzięki za tę wskazówkę.
Ravi
7

1: - Wygląda na to, że musimy zaktualizować wersję bazy danych (przyrost o 1)

wprowadź opis obrazu tutaj

2. Odinstaluj aplikację lub Wyczyść dane aplikacji

Keshav Gera
źródło
6

Na telefonie z systemem Android:

Odinstaluj aplikację lub Wyczyść dane aplikacji

Aby usunąć dane aplikacji: Przejdź do ustawień -> Aplikacje -> Wybierz swoją aplikację -> Pamięć -> Wyczyść dane

Odinstalowanie (i ponowna instalacja) nie działa w każdym przypadku, więc najpierw spróbuj wyczyścić dane!

Marci
źródło
Tak, to zadziałało. Ale o dziwo dostałem ten problem na urządzeniu, które zostało całkowicie usunięte i skonfigurowane od nowa. Ale po prostu wyczyszczenie danych rozwiązanych.
Ajith Memana
Nie należy tego robić na produkcji. Nie należy zmuszać wszystkich użytkowników do usuwania danych z aplikacji. Lepiej pisać kod migracji, zwiększając wersję o 1 w bazie danych Room.
Rajeev Jayaswal
5

W moim przypadku zmiana android:allowBackup="false"z prawdziwego na fałszywy zadziałała, ponieważ dawało mi to koszmary również wcześniej, to najdziwniejsza rzecz, dlaczego to ustawienie jest domyślnie włączone!

Divyanshu Negi
źródło
4

Ten problem występuje głównie w fazie rozwoju.

W przypadku zmiany schematu, tj. Zmiany nazwy / dodania / zmodyfikowania klasy zawierającej jednostkę tabeli, integralność między wyjściem z bazy danych w poprzedniej kompilacji powoduje konflikt z nową kompilacją.

wyczyść dane aplikacji lub zainstaluj nową kompilację po odinstalowaniu poprzedniej kompilacji .

Teraz stara baza danych nie będzie kolidować z nowszą.

Extremis II
źródło
Po tym nadal występuje awaria
user7856586
co jest wyjątkiem proszę odłóż dziennik, aby zawęzić problem.
Extremis II
2
Dzięki, teraz wszystko jest w porządku. Czytam o tym android:allowBackup="true"i używam go mądrze
user7856586
1
@ user7856586 A co z allowBackup? Czy mógłbyś nas oświecić swoją mądrością?
Ridcully,
@Ridcully, możesz o tym przeczytać tutaj Dlaczego jesteś taki zły?
user7856586
4

Aby rozwiązać problem w Kotlin:

Pierwszy

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

druga

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

Trzeci

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

Aby uzyskać więcej informacji, zapoznaj się z oficjalną dokumentacją

peterzinho16
źródło
3

W moim przypadku miałem klasę AppDatabase.

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

Zaktualizowałem ten numer wersji i rozwiązałem problem. Wystąpił problem, ponieważ dodałem właściwość w klasie SongInfo i zapomniałem zaktualizować numer wersji.

Mam nadzieję, że to komuś pomoże.

Harry .Naeem
źródło
2

Jeśli aktualizujesz wersję Room do 1.0.0-alpha9 ze starej wersji, odwiedź poniższy artykuł. Bardzo dobry artykuł do migracji ze starej wersji do wersji 1.0.0-alpha9.

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

W pokoju Nowa wersja 1.0.0-alpha9 Room dodaje obsługę ograniczenia NOT NULL.

To zmieni schemat generowany przez Room. Ponieważ zmienia schemat, zmienia również tożsamość skrótu bazy danych i jest używany przez Room do unikatowego identyfikowania każdej wersji bazy danych. Dlatego potrzebujemy migracji

Bhargav Pandya
źródło
2

W moim przypadku ContentProvider i baza danych pokoju współpracują, więc najpierw usuń wszystkie wywołania zwrotne ContentProvider w całej aplikacji z klasą bazy danych, która rozszerza klasę SqlLiteOpenHelper

Chaman
źródło
2

W moim przypadku korzystałem z transakcji w ramach migracji i Room nie mógł zaktualizować skrótu za pomocą pomocnika migracji

@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
źródło
Walczę kilka godzin i to było rozwiązanie !! Dziękuję Ci!!
Javier
1
W powyższym przykładzie to nie transakcja jest problemem. Zapomniałeś ustawić transakcję jako pomyślną przed jej zakończeniem: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </code> </pre>
birukoff
2
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

Zmień numer wersji w klasie RoomDatabase. Zwiększ numer wersji.

Rajeev Shetty
źródło
2

Jeśli zwiększenie wersji schematu nie zadziałało, zapewnij migrację bazy danych. Aby to zrobić musisz zadeklarować migrację w kreatorze baz danych:

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
źródło
Tak, to jest właściwa droga
Bipin Bharti
1

Właśnie miałem podobny problem w teście espresso i jedyną rzeczą, która go naprawiła, było wyczyszczenie danych, a także odinstalowanie aplikacji testowych Androidx, takich jak:

adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services
Daniel Jonker
źródło
0

W moim przypadku robiłem aktualizację bazy danych, którą będę wstępnie pakować z moją aplikacją. Żadna z poniższych sugestii nie zadziałała. Ale w końcu doszedłem do wniosku, że mogę otworzyć plik .db w programie bazodanowym (użyłem „DB Browser for SQLite”) i ręcznie zmienić „User version” z 2 na 1. Potem wszystko działało idealnie.

Wydaje mi się, że każda aktualizacja, którą wprowadzasz, zmienia tę wersję użytkownika i dlatego ciągle otrzymuję ten błąd.

Gavin Wright
źródło
Czy możesz mi w tym pomóc? Nie mogę znaleźć wersji w przeglądarce DB dla SQLite
GreenROBO
Znajduje się na karcie „Edytuj pragmy”. Nazywa się „Wersja użytkownika”.
Gavin Wright
Tak. Mam to. Dzięki za pomoc Gavin :)
GreenROBO
-1

W moim przypadku wypróbowałem wszystkie powyższe. Wydawało się, że nic nie działa, więc rozwiązaniem dla mnie było po prostu ustawienie android:allowBackup="false", zainstalowanie aplikacji, a następnie przywrócenie jej wartości true

Mam nadzieję, że pomoże to innym :)

gmartinsnull
źródło
1
To jest dokładnie to, na co odpowiedziałem, po co powtarzać odpowiedź?
Divyanshu Negi
-2

Ten sam błąd wystąpił podczas programu szkoleniowego Codelabs. Gdzie W jednej sesji szkoleniowej stworzyłem projekt i działał pomyślnie ze wszystkimi operacjami na bazie danych. W następnej sesji pracowałem z innym repozytorium, ale było to rozszerzenie poprzedniego projektu. Tylko od pierwszej kompilacji aplikacji rozszerzonej wystąpił błąd.

Może Studio zachowuje techniki uwierzytelniania w bazie danych pokoi, której brakuje w nowej kompilacji.

Shrinivas Manjithaya
źródło