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


94

Я отримую цю помилку під час запуску програми з Room Database

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
Я хотів би, щоб вони включили для цього випадку ще один резервний метод :(
BoD

3
У версії 1.0.0-rc1Room єдине, що мені вдалося, - це збільшити версію бази даних.
Dick Lucas

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

1
@Bartek цей коментар зараз заслуговує на відповідь.
guness

Таке пояснення! Я видаляв програму знову і знову, бо навіщо оновлювати версію в розробці? О, хлопче, я ніколи не думав, що очищення даних із налаштувань є ключовим фактором. Приємна відповідь. Має бути прийнятим рішенням.
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
Садат

@ nimi0112 Для вашого варіанту випуску слід дозволити резервне копіювання, однак для свого варіанту налагодження ви можете його вимкнути
Чад Mx

25

android: allowBackup = "true" всередині AndroidManifest.xml запобігає очищенню даних навіть після видалення програми.

Додайте це до свого маніфесту:

android:allowBackup="false"

та переінсталюйте програму.

Примітка. Переконайтеся, що ви знову змінили його на true, якщо хочете автоматичне резервне копіювання.

Інше рішення:

Перевірте identHash вашого старого 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.");
    }
}

20

Відповідь Анірудд Парихар дав мені підказку і вирішив.

Шукайте клас, який ви продовжили RoomDatabase. Там ви знайдете версію, як показано нижче:

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

просто збільште версію і проблема вирішена.


11

Це дуже просто, як показано в журналі

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 з поточної.

Наприклад: Знайдіть у своєму проекті анотацію @Database, як показано нижче

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

Тут версія = 1, це версія бази даних, вам потрібно просто збільшити її на одну, ось і все.


1
Так, я отримав цю помилку, тому я також згадав про це It seems we need to update database version. Але я не дійшов там, де згадувалася ця версія. У будь-якому разі дякую за цей натяк.
Раві

Ви переформулювали повідомлення про помилку, але не надали жодної додаткової інформації, щоб усунути плутанину оригінального плаката.
Карл Росман

@CarlRossman: Ви повинні знайти свій клас бази даних у своєму проекті, де ви використовували анотацію бази даних, у цьому класі ви знайдете версію бази даних (ціле значення), просто збільште її на одну з поточної.
Анірудд Парихар

7

1: - Здається, нам потрібно оновити версію бази даних (збільшення на 1)

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

2-е Видаліть програму або Очистіть дані програми


6

На телефоні android:

Видаліть програму або Очистіть дані програми

Щоб видалити дані програми: Перейдіть у налаштування -> Програми -> Виберіть свою програму -> Пам'ять -> Очистити дані

Видалення (та перевстановлення) працює не у всіх випадках, тому спробуйте спочатку очистити дані!


Так, це спрацювало. Але як не дивно, я отримував цю проблему на пристрої, який повністю стервся і налаштувався заново. Але просто очищення даних вирішено.
Аджит Мемана

Цього не слід робити на виробництві. Не слід примушувати всіх своїх користувачів видаляти дані з програми. Краще писати міграційний код, збільшуючи версію на 1 у вашій базі даних Room.
Раджеєв Джаясвал,

5

У моєму випадку android:allowBackup="false"перехід від істинного до хибного спрацював, оскільки це також давало мені кошмари і раніше, це найдивніше, чому цей параметр увімкнено за замовчуванням!


5

Щоб вирішити проблему в kotlin:

Спочатку

@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 у вашій попередній збірці конфліктує з новою збіркою.

очистіть дані програми або встановіть нову збірку після видалення попередньої збірки .

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


Після цього все ще аварія
user7856586

який виняток? будь ласка, викладіть журнал, щоб звузити проблему.
Екстреміс II

2
Дякую, зараз все в порядку. Я читав android:allowBackup="true"і мудро використовую це
user7856586

1
@ user7856586 То як щодо дозволеного резервного копіювання? Не могли б ви просвітити нас своєю мудрістю?
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 Room додає підтримку обмеження NOT NULL.

Це змінить схему, яку генерує Room. Оскільки він змінює схему, він також змінює ідентифікаційний хеш БД, який використовується 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

Я просто мав подібну проблему в тесті еспресо, і єдине, що це виправило, - це очищення даних, а також видалення тестових apk для androidx, таких як:

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

0

У моєму випадку я оновлював базу даних, яку буду попередньо упаковувати у свій додаток. Жодна з пропозицій тут не спрацювала. Але нарешті я зрозумів, що можу відкрити файл .db у програмі баз даних (я використовував "Браузер DB для SQLite") і вручну змінити "Версію користувача" з 2 назад на 1. Після цього він працював чудово.

Я думаю, будь-яке оновлення, яке ви вносите, змінює цю версію користувача, і саме тому я постійно отримував цю помилку.


Чи можете ви допомогти мені з тим самим? Я не можу знайти версію в браузері DB для SQLite
GreenROBO

Це на вкладці "Редагувати прагми". Це називається "Версія користувача".
Гевін Райт,

Так. Зрозумів. Дякую за допомогу, Гавін :)
GreenROBO

-1

У моєму випадку я спробував усе вищесказане. Здавалося, нічого не працює, тому рішення для мене було просто налаштуванням android:allowBackup="false", встановіть програму, а потім встановіть її назад на істину

Сподіваюся, це допомагає іншим :)


1
Це саме те, що я відповів, навіщо повторювати відповідь?
Дів'яншу Негі,

-2

Я отримав ту ж помилку під час навчальної програми Codelabs. Де За одну навчальну сесію я створив проект, і він успішно працював з усіма операціями з базами даних. У наступній сесії я працював з іншим репо, але це було продовженням попереднього проекту, лише з першої збірки розширеного додатка я отримав помилку.

Можливо, Studio зберігає методи автентифікації з базою даних кімнати, якої немає в новій збірці.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.