Комната не может проверить целостность данных


92

Я получаю эту ошибку при запуске программы с базой данных номеров

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.

Кажется, нам нужно обновить версию базы данных, но откуда мы можем это сделать в комнате?


2
Если вам не важны данные приложения, удаление всего содержимого из настроек приложения также может помочь, так как оно просто уничтожает всю БД
O-9

Ответы:


131

Когда вы впервые столкнетесь с этим сообщением, скорее всего, вы работаете с невыпущенной версией базы данных. В таком случае, скорее всего, вам не следует увеличивать версию базы данных . Простая очистка данных приложения переместит вас в исключение.

Если вы не увеличиваете базу данных (рекомендуется):

Вам следует удалить данные приложения в настройках Android. В качестве альтернативы вы можете удалить предыдущую версию приложения, а затем установить новую версию, чтобы передать исключение. Последний подход не работает при определенных условиях (например, когда разрешено резервное копирование).

Поскольку очистка данных приложения всегда работает, я всегда выбираю этот путь.

Если вы увеличиваете версию базы данных:

Вам нужно будет написать код миграции базы данных, чтобы учесть любые изменения в схеме базы данных. См. Здесь информацию о миграции.

Альтернативой написанию кода миграции базы данных является вызов fallbackToDestructiveMigrationпостроителя базы данных Room. Вероятно, это плохая идея. Если вы забудете удалить этот вызов, а затем забудете обновить базу данных, это приведет к потере данных.

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

Опять же, ни увеличение версии базы данных, ни возврат к деструктивной миграции не требуется, если предыдущая схема базы данных еще не используется .


4
Я бы хотел, чтобы они включили другой запасной метод для этого случая :(
директоров

3
В версии 1.0.0-rc1Room единственное, что у меня сработало, - это увеличить версию базы данных.
Дик Лукас,

42
У меня был android: allowBackup = "true" в моем AndroidManifest.xml, который предотвращал удаление данных даже после удаления приложения. Я установил для этого атрибута значение false, а затем переустановил приложение, что помогло избавиться от проблемы. Обратите внимание, что true - это значение по умолчанию для allowBackup, поэтому, если вы его вообще не используете, это может привести к сохранению данных.
Bartek

1
@Bartek, этот комментарий теперь заслуживает ответа.
guness 04

Такое объяснение! Я снова и снова удалял приложение, потому что зачем обновлять разрабатываемую версию? О боже, никогда не думал, что очистка данных из настроек - ключ к успеху. Хороший ответ. Должно быть приемлемое решение.
sud007

29

По умолчанию в манифесте Android есть android:allowBackup="true", что позволяет приложениям сохранять свою базу данных SQLite при переустановке.

Предположим, у вас DATABASE_VERSIONизначально было 3, а затем вы решили уменьшить версию БД с 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.
//        }
//    };
}

Вы можете добиться этого так

  • Удалите данные приложения из настроек. Это удалит старую БД (DATABASE_VERSION = 3) с телефона
  • Удалите ваше приложение
  • Уменьшите версию DATABASE_VERSION до 1
  • Создайте и переустановите свое приложение

Хорошая практика - поддерживать DATABASE_VERSIONпостоянство.


1
Не повлияет ли это на пользователей, которые будут обновлять приложение из игрового магазина?
nimi0112

1
Я пошел по тому же пути, но не сработало. Даже когда я пытаюсь установить новое устройство из Android Studio, он показывает ту же ошибку: x
Sadat

@ nimi0112 Для вашего варианта выпуска вы должны разрешить резервное копирование, однако для вашего варианта отладки вы можете отключить его
Chad Mx

25

android: allowBackup = "true" в файле AndroidManifest.xml предотвращает очистку данных даже после удаления приложения.

Добавьте это в свой манифест:

android:allowBackup="false"

и переустановите приложение.

Примечание. Убедитесь, что вы изменили его обратно на true позже, если хотите автоматическое резервное копирование.

Другое решение:

Проверьте identityHash своего старого файла json и нового файла json в папке apps \ schema.

Если identityHash отличается, он выдаст эту ошибку. Узнайте, что вы изменили, сравнив оба файла json, если вы не хотите ничего менять.

Убедитесь, что у вас есть exportSchema = true.

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

файл схемы json:

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

код:

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.");
    }
}


12

Это очень просто, как показано в журнале

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

Просто перейдите в класс версии базы данных и обновите версию своей БД, увеличив 1 по сравнению с текущей.


1
Да, я получил эту ошибку, поэтому я также упомянул об этом It seems we need to update database version. Но я не понимал, где упоминалась эта версия. В любом случае спасибо за подсказку.
Рави

7

1: - Похоже, нам нужно обновить версию базы данных (увеличить на 1)

введите описание изображения здесь

2. Удалите приложение или очистите данные приложения.


6

На телефоне Android:

Удалите приложение или очистите данные приложения

Чтобы удалить данные приложения: перейдите в настройки -> Приложения -> Выберите приложение -> Хранилище -> Очистить данные.

Удаление (и повторная установка) работает не во всех случаях, поэтому сначала попробуйте очистить данные!


Да, это сработало. Но, как ни странно, у меня возникла эта проблема на устройстве, которое было полностью стерто и настроено только что. Но простая очистка данных решена.
Аджит Мемана

Этого не следует делать на производстве. Вы не должны заставлять всех своих пользователей удалять данные из приложения. Лучше написать код миграции, увеличив версию на 1 в базе данных Room.
Раджив Джаясвал,

5

В моем случае android:allowBackup="false"сработало переключение с истины на ложь, так как это и раньше доставляло мне кошмары, это самая странная вещь, почему этот параметр включен по умолчанию!


5

Чтобы исправить проблему в котлине:

Первый

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

Второй

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

Третий

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

Более подробную информацию можно найти в официальной документации.


4

Эта проблема чаще всего возникает в процессе разработки.

Если вы измените схему, то есть переименуете / добавите / измените свой класс, содержащий объект таблицы, целостность между выходом из базы данных в вашей предыдущей сборке конфликтует с новой сборкой.

очистите данные приложения или установите новую сборку после удаления предыдущей сборки .

Теперь старый db не будет конфликтовать с новым.


После этого все еще вылет
user7856586

какое исключение? пожалуйста, поднимите журнал, чтобы сузить круг вопросов.
Extremis II

2
Спасибо, теперь все ок. Я читал об этом android:allowBackup="true"и использую его с умом
user7856586

1
@ user7856586 Так что насчет allowBackup? Не могли бы вы просветить нас своей мудростью?
Ridcully

@ Ridcully, ты можешь прочитать об этом здесь. Почему ты так зол?
user7856586

3

В моем случае у меня был класс AppDatabase.

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

Я обновил этот номер версии, и проблема была решена. Проблема возникла из-за того, что я добавил свойство в класс SongInfo и забыл обновить номер версии.

Надеюсь, это кому-то поможет.


2

Если вы обновляете версию Room до 1.0.0-alpha9 со старой версии, пожалуйста, прочтите статью ниже. Очень хорошая статья для перехода со старой версии на версию 1.0.0-alpha9.

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

В комнате Новая версия 1.0.0-alpha9 В комнате добавлена ​​поддержка ограничения NOT NULL.

Это изменит схему, которую генерирует Room. Поскольку он изменяет схему, он также изменяет identityHash БД, который используется Room для уникальной идентификации каждой версии БД. Следовательно, нам нужна миграция


2

В моем случае ContentProvider и база данных комнаты работают вместе, поэтому сначала удалите все обратные вызовы ContentProvider по всему приложению с классом базы данных, который расширяет класс SqlLiteOpenHelper


2

В моем случае я использовал транзакцию внутри миграции, и Room не смог обновить хэш с помощью Помощника по миграции.

@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() 
}

Я борюсь несколько часов, и это было решением !! Спасибо!!
Хавьер

1
В приведенном выше примере проблема не в транзакции. Вы забыли установить успешную транзакцию перед ее завершением: <pre> <code> database.beginTransaction () database.setTransactionSuccessful () database.endTransaction () </code> </pre>
birukoff

2
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

Измените номер версии в своем классе RoomDatabase. Увеличьте номер версии.


2

Если увеличение версии схемы у вас не помогло, предоставьте миграцию вашей базы данных. Для этого нужно объявить миграцию в построителе базы данных:

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

Да, это правильный путь
Бипин Бхарти

1

У меня была аналогичная проблема в тесте эспрессо, и единственное, что исправило это, - это очистка данных, а также удаление тестовых apks androidx, например:

adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services

0

В моем случае я обновлял базу данных, которую я буду предварительно упаковывать вместе со своим приложением. Ни одно из предложений здесь не сработало. Но я наконец понял, что могу открыть файл .db в программе базы данных (я использовал «Браузер БД для SQLite») и вручную изменить «Пользовательскую версию» с 2 на 1. После этого все заработало отлично.

Я предполагаю, что любое обновление, которое вы вносите, изменяет эту пользовательскую версию, и именно поэтому я продолжал получать эту ошибку.


Можете ли вы помочь мне с тем же? Я не могу найти версию в браузере БД для SQLite
GreenROBO

Он находится на вкладке «Редактировать прагмы». Это называется «Пользовательская версия».
Гэвин Райт,

Да. Я понял. Спасибо за помощь, Гэвин :)
GreenROBO

-1

В моем случае я попробовал все вышеперечисленное. Казалось, что ничего не работает, поэтому решение для меня было просто настроить android:allowBackup="false", установить приложение, а затем вернуть его в значение true

Надеюсь, это поможет другим :)


1
Это именно то, что я ответил, зачем повторять ответ?
Дивяншу Неги,

-2

У меня такая же ошибка возникла во время программы обучения Codelabs. Где На одном учебном занятии я создал проект, и он успешно выполнил все операции с базой данных. В следующем сеансе я работал с другим репозиторием, но это было расширение предыдущего проекта. Только из первой сборки расширенного приложения у меня была ошибка.

Возможно, Studio сохраняет методы аутентификации с базой данных комнат, которые отсутствуют в новой сборке.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.