会议室无法验证数据完整性


92

使用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中完成呢?


2
如果您不关心应用程序的数据,则从应用程序设置中删除所有内容也可能会有所帮助,因为这只会破坏整个数据库
O-9

Answers:


131

当您第一次遇到此消息时,您很可能正在使用数据库的未发行版本。在这种情况下,很可能您不应该增加数据库版本。只需清除应用程序数据将使您通过异常。

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

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

由于清除应用程序数据始终有效,因此我每次都采用这种方法。

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

您将需要编写数据库迁移代码来说明对数据库模式的任何更改。有关迁移的信息,请参见此处

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

// 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版本中,对我有用的唯一方法是增加数据库版本。
迪克·卢卡斯

42
我的AndroidManifest.xml中有android:allowBackup =“ true”,即使在卸载应用程序后,该数据也无法清除。我将此属性设置为false,然后重新安装了该应用程序,这有助于解决该问题。请注意,true是allowBackup的默认值,因此,如果您根本不使用它,则可能仍会保留数据。
Bartek

1
@Bartek此评论现在应该作为答案。
guness

这样的解释!我一次又一次卸载该应用程序,因为为什么要升级开发中的版本?哦,天哪,从来没有想过清除设置中的数据是前进的关键。好答案。应该是公认的解决方案。
sud007 '19

29

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

假设您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.
//        }
//    };
}

你可以这样实现

  • 从设置中清除应用数据。这将从电话中删除较旧的DB(DATABASE_VERSION = 3)
  • 卸载您的应用
  • 将DATABASE_VERSION版本减少到1
  • 生成并重新安装您的应用

保持DATABASE_VERSION不变是一个好习惯。


1
不会影响将要从Play商店更新应用程序的用户吗?
nimi0112

1
我遵循相同的方法,但是没有用。即使我尝试从Android Studio安装在新设备上,它也会显示相同的错误:x
Sadat

@ nimi0112对于您的发行版本,应该允许备份,但是对于您的调试版本,您可以将其关闭
Chad Mx19年

25

即使卸载了应用程序,AndroidManifest.xml中的android:allowBackup =“ true”仍可防止清除数据。

将此添加到清单中:

android:allowBackup="false"

并重新安装该应用。

注意:如果要自动备份,请确保稍后将其更改为true。

另一个解决方案:

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

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

19

Aniruddh Parihar的回答给了我一个提示,并解决了。

搜索您已扩展的课程RoomDatabase。在那里,您将找到类似以下的版本:

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

只需增加版本即可解决问题。


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手机上:

卸载应用程序清除应用程序数据

删除应用程序数据:转到设置->应用程序->选择您的应用程序->存储->清除数据

卸载(并重新安装)在每种情况下均不起作用,因此请先尝试清除数据!


是的,行得通。但是奇怪的是,我在完全擦除并刚刚重新设置的设备上遇到了这个问题。但是只需清除数据即可解决。
Ajith Memana

不应在生产中执行此操作。您不应强迫所有用户清除应用程序中的数据。最好通过在Room数据库中将版本增加1来编写迁移代码。
Rajeev Jayaswal

5

就我而言android:allowBackup="false",使它从true变为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与新构建之间的完整性会发生冲突。

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

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


在那之后仍然崩溃
user7856586 '18

有什么例外?请张贴日志以缩小问题范围。
Extremis II '18

2
谢谢,一切都很好。我了解android:allowBackup="true"并明智地使用了它
user7856586

1
@ user7856586那么allowBackup呢?您能用您的智慧启发我们吗?
Ridcully

@Ridcully,您可以在此处阅读有关内容的信息。 为什么您如此生气?
user7856586 18/12/24

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

在Room新版本1.0.0-alpha9中,Room添加了对NOT NULL约束的支持。

那将改变Room生成的模式。因为它更改了架构,所以它也更改了数据库的identityHash,Room用来唯一标识每个数据库版本。因此,我们需要迁移


2

在我的情况下,ContentProvider和会议室数据库一起工作,因此首先使用扩展SqlLiteOpenHelper类的数据库类在整个应用程序中删除ContentProvider的所有回调


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

如果增加的架构版本对您不起作用,请提供数据库的迁移。为此,您需要在数据库构建器中声明迁移:

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

是的,这是正确的方法
Bipin Bharti

1

我在espresso测试中遇到了类似的问题,解决该问题的唯一方法是清除数据并卸载androidx测试apk,例如:

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

0

就我而言,我正在对数据库进行更新,该数据库将与我的应用程序预先打包在一起。这里的建议都没有奏效。但是我最终发现,可以在数据库程序中打开.db文件(我使用“ SQLite的数据库浏览器”),然后将“用户版本”从2手动更改回1。此后,它可以正常工作。

我猜您对该用户版本进行的任何更新都会更改,这就是为什么我一直收到此错误的原因。


你能帮我吗?我在数据库浏览器中找不到用于SQLite的版本
GreenROBO

在“编辑编译指示”标签下。它称为“用户版本”。
加文·赖特

是。我知道了。感谢您的帮助加文:)
GreenROBO

-1

就我而言,我尝试了以上所有方法。似乎没有任何效果,因此对我来说,解决方案是简单地设置android:allowBackup="false",安装应用程序然后将其设置为true

希望它对其他人有帮助:)


1
这正是我所回答的,为什么要重复回答?
Divyanshu Negi

-2

在Codelabs的培训计划中,我遇到了相同的错误。在一个培训课程中,我创建了一个项目,该项目在所有数据库操作中均成功运行。在下一个会话中,我正在使用另一个仓库,但这是先前项目的扩展,从扩展应用程序的第一版开始,只有我遇到了错误。

也许Studio保留了新版本缺少的会议室数据库的身份验证技术。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.