房间无法验证数据的完整性

问题描述 投票:41回答:12

使用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.

我们似乎需要更新数据库版本,但是我们可以在Room中从哪里做到这一点?

android android-database android-room
12个回答
76
投票

当您第一次看到此消息时,您很可能正在使用未发布的数据库版本。如果是这种情况,很可能您不应该增加数据库版本。只需清除应用数据即可移动您通过异常。

如果不增加数据库(推荐):

您应该从Android设置中清除应用程序的应用程序数据。您也可以卸载以前的应用程序版本,然后安装新版本以通过异常。后一种方法在某些条件下不起作用(例如启用允许备份时)

由于清除应用程序数据始终有效,因此我每次都会使用该路径。

如果您确实增加了数据库版本:

您需要编写数据库迁移代码以解释对数据库模式的任何更改。有关迁移的信息,请参阅here

编写数据库迁移代码的替代方法是在Room数据库构建器上调用fallbackToDestructiveMigration。这可能不是一个好主意。忘记删除此调用,然后忘记升级数据库将导致数据丢失。

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

同样,如果先前的数据库模式不是在野外存在,则既不需要递增数据库版本也不回退到破坏性迁移。


2
投票

在我的案例中,ContentProvider和room数据库一起工作,所以首先在整个应用程序中删除ContentProvider的所有回调,其中包含扩展SqlLiteOpenHelper类的数据库类


2
投票

在我的情况下,我在迁移中使用了一个事务,而Room无法使用Migration Helper更新哈希

@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
投票

在我的情况下,我尝试了以上所有。似乎没有什么工作,所以我的解决方案只是设置android:allowBackup="false",安装应用程序然后将其设置回true

希望它能帮助别人:)


0
投票

我在espresso测试中遇到了类似的问题,修复它的唯一问题是清除数据并卸载androidx测试apks,如:

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

13
投票

默认情况下,Android清单有android:allowBackup="true",允许应用程序在重新安装时保留其SQLite数据库。

假设您的DATABASE_VERSION最初为3,然后您决定将DB版本从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.
//        }
//    };
}

你可以像这样实现它

  • 清除设置中的应用数据。这将从手机中删除旧的DB(DATABASE_VERSION = 3)
  • 卸载您的应用程序
  • 将DATABASE_VERSION版本减少为1
  • 构建并重新安装您的应用程序

保持DATABASE_VERSION不变是一个很好的做法。


11
投票

它非常简单,如日志所示

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

简单地转到您的数据库类并通过从当前增加1来升级您的数据库版本。


9
投票

Aniruddh Parihar的回答给了我一个暗示,它解决了。

搜索扩展RoomDatabase的类。你会在那里找到如下版本:

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

只是增加版本,问题就解决了。


4
投票

此问题主要发生在开发中。

如果更改架构,即重命名/添加/修改包含表实体的类,则先前构建中退出db与新构建之间的完整性会发生冲突。

卸载以前的版本后清除应用程序数据或安装新版本。

现在,旧数据库不会与新数据库发生冲突。


4
投票

在我的情况下android:allowBackup="false"使它从真实到虚假工作,因为这也给了我以前的噩梦,这是最奇怪的事情,为什么这个设置默认启用!


3
投票

在我的例子中,我有一个AppDatabase类。

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

我更新了这个版本号,它解决了这个问题。出现问题是因为我在SongInfo类中添加了一个属性而忘记更新版本号。

希望它可以帮助某人。


3
投票

AndroidManifest.xml中的android:allowBackup =“true”即使在卸载应用程序后也会阻止数据被清除。

将此添加到您的清单:

android:allowBackup="false"

并重新安装该应用程序。

另一种方案:

检查旧json文件的identityHash和apps \ schema文件夹中的新json文件。

如果身份Hash不同,它将给出该错误。如果您不想更改任何内容,请通过比较两个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.");
    }
}

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

In Room新版本1.0.0-alpha9 Room增加了对NOT NULL约束的支持。

这将改变Room生成的架构。因为它会更改架构,所以它还会更改数据库的identityHash以及Room用于唯一标识每个数据库版本的身份。因此,我们需要迁移

© www.soinside.com 2019 - 2024. All rights reserved.