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?
Odpowiedzi:
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
fallbackToDestructiveMigration
konstruktora 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 .
źródło
1.0.0-rc1
Room jedyną rzeczą, która działała dla mnie, było zwiększenie wersji bazy danych.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_VERSION
począ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
To dobra praktyka, aby zachować
DATABASE_VERSION
taką stałą.źródło
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."); } }
źródło
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.
źródło
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.
źródło
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ę.1: - Wygląda na to, że musimy zaktualizować wersję bazy danych (przyrost o 1)
2. Odinstaluj aplikację lub Wyczyść dane aplikacji
źródło
Na telefonie z systemem Android:
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!
źródło
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!źródło
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ą.
Teraz stara baza danych nie będzie kolidować z nowszą.
źródło
android:allowBackup="true"
i używam go mądrzeAby 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ą
źródło
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.
źródło
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
źródło
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
źródło
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() }
źródło
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)
Zmień numer wersji w klasie RoomDatabase. Zwiększ numer wersji.
źródło
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"); } };
źródło
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
źródło
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.
źródło
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 trueMam nadzieję, że pomoże to innym :)
źródło
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.
źródło