Room 无法验证数据完整性。如何在不编写迁移步骤的情况下修复它?

Posted

技术标签:

【中文标题】Room 无法验证数据完整性。如何在不编写迁移步骤的情况下修复它?【英文标题】:Room cannot verify the data integrity. How can I fix it without writing migration steps? 【发布时间】:2019-12-17 22:31:27 【问题描述】:

我在生产应用程序上设置了房间。 我在我的应用中对多个表进行了许多与架构相关的更改。

在交付到生产版本之前,我已经确定了以下内容

    增加数据库版本 在@Database注释行中有exportSchema = false allowBackup 在清单<application android:allowBackup="false" /> 中设置为 false 在创建数据库时拥有.fallbackToDestructiveMigration() 在创建数据库时拥有.fallbackToDestructiveMigrationOnDowngrade() 在创建数据库时拥有.enableMultiInstanceInvalidation()

应用程序因以下堆栈跟踪而崩溃。

java.lang.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.

对于开发,我可以清除应用缓存和数据,但如何在生产中解决这个问题? 我不想编写迁移步骤,因为架构和表中有多个更改。

我已阅读excellent article,但没有帮助。我有哪些选择?

堆栈跟踪

Fatal Exception: java.lang.RuntimeException: Exception while computing database live data.
   at androidx.room.RoomTrackingLiveData$1.run + 92(RoomTrackingLiveData.java:92)
   at java.util.concurrent.ThreadPoolExecutor.runWorker + 1167(ThreadPoolExecutor.java:1167)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run + 641(ThreadPoolExecutor.java:641)
   at java.lang.Thread.run + 764(Thread.java:764)

/////////////////////////

Caused by java.lang.IllegalStateException: A migration from 19 to 20 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
   at androidx.room.RoomOpenHelper.onUpgrade + 101(RoomOpenHelper.java:101)
   at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade + 124(FrameworkSQLiteOpenHelper.java:124)
   at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked + 398(SQLiteOpenHelper.java:398)
   at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase + 298(SQLiteOpenHelper.java:298)
   at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase + 92(FrameworkSQLiteOpenHelper.java:92)
   at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase + 53(FrameworkSQLiteOpenHelper.java:53)
   at androidx.room.RoomDatabase.inTransaction + 452(RoomDatabase.java:452)
   at androidx.room.RoomDatabase.assertNotSuspendingTransaction + 275(RoomDatabase.java:275)
   at androidx.room.RoomDatabase.query + 304(RoomDatabase.java:304)
   at androidx.room.util.DBUtil.query + 54(DBUtil.java:54)
   at com.xxx.data.local.banner.BannerDao_Impl$4.call + 218(BannerDao_Impl.java:218)
   at com.xxx.data.local.banner.BannerDao_Impl$4.call + 215(BannerDao_Impl.java:215)
   at androidx.room.RoomTrackingLiveData$1.run + 90(RoomTrackingLiveData.java:90)
   at java.util.concurrent.ThreadPoolExecutor.runWorker + 1167(ThreadPoolExecutor.java:1167)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run + 641(ThreadPoolExecutor.java:641)
   at java.lang.Thread.run + 764(Thread.java:764)

【问题讨论】:

保留.fallbackToDestructiveMigration() 并删除.fallbackToDestructiveMigrationOnDowngrade(),因为后者会覆盖之前的设置。 试过了,但没用 【参考方案1】:

我使用以下方法解决了 Room 迁移问题。

 Room.databaseBuilder(context, AppDatabase::class.java, "xxx.db")
        .fallbackToDestructiveMigration()
        .fallbackToDestructiveMigrationOnDowngrade()
        .fallbackToDestructiveMigrationFrom(16, 17, 18, 19)
        .build() 

必须添加 fallbackToDestructiveMigrationFrom() 方法,该方法强制删除表并使用新架构重新创建表。

因此 db 版本的 varargs 例如 16, 17, 18, 19 将为方法 fallbackToDestructiveMigrationFrom(...) 的这些版本号重新创建 db

不知道为什么这种方法有效但fallbackToDestructiveMigration() 无效。

为什么这么奇怪?

【讨论】:

以上是关于Room 无法验证数据完整性。如何在不编写迁移步骤的情况下修复它?的主要内容,如果未能解决你的问题,请参考以下文章

Room:使用 fallbackToDestructiveMigrationFrom() 进行迁移如何工作?

迁移数据库时合并用户的 Android Room 数据库

Android-Room 可以自动创建迁移吗?

Room 中的数据库自动迁移功能

Room 中的数据库迁移

Android Room迁移测试:主键位置的差异导致无根据的测试失败