123

使用 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 中从哪里进行更新呢?

4

20 回答 20

165

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

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

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

由于清除应用程序数据总是有效的,所以我每次都走这条路。

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

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

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

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

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

于 2017-08-30T18:59:46.463 回答
40

AndroidManifest.xml 中的 android:allowBackup="true" 可防止在卸载应用后清除数据。

将此添加到您的清单中:

android:allowBackup="false"

并重新安装应用程序。

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

另一种解决方案:

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

如果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.");
    }
}
于 2018-11-17T16:41:28.617 回答
36

默认情况下,Android manifest 有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不变是一个很好的做法。

于 2018-01-17T02:58:24.017 回答
26

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

搜索您已扩展的课程RoomDatabase。在那里你会找到如下版本:

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

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

于 2017-05-26T09:07:05.653 回答
22

它非常简单,如日志所示

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)

这里的version = 1,是数据库版本,你只需要加一就行了。

于 2017-05-26T08:51:19.333 回答
9

不要在生产代码中使用此解决方案!
请改用Aniruddh Parihar 的答案peterzinho16 的答案

在安卓手机上:

卸载应用清除应用数据

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

卸载(并重新安装)并非在所有情况下都有效,因此请先尝试清除数据!

于 2019-08-14T11:44:50.317 回答
9

1:- 看来我们需要更新数据库版本(递增 1)

在此处输入图像描述

第二次卸载应用程序或清除应用程序数据

于 2019-09-03T09:32:48.263 回答
9

为了解决 kot​​lin 中的问题:

第一的

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

更多详细信息,请查看官方文档

于 2020-04-09T23:19:41.180 回答
7

就我而言android:allowBackup="false",将其从真变为假是可行的,因为这也让我做噩梦,这是最奇怪的事情,为什么默认启用此设置!

于 2019-03-24T19:28:43.700 回答
4

这个问题主要发生在开发中。

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

卸载前一个版本后清除应用数据安装新版本

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

于 2018-08-19T18:36:46.683 回答
3

在我的情况下,我在迁移中使用了一个事务,并且 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() 
}
于 2018-04-18T22:38:54.173 回答
3

就我而言,我有一个 AppDatabase 类。

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

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

希望它可以帮助某人。

于 2018-07-21T08:59:10.020 回答
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 New Version 1.0.0-alpha9 Room 添加了对 NOT NULL 约束的支持。

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

于 2017-08-31T13:43:24.970 回答
2

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

于 2018-04-06T09:22:11.740 回答
2
@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

更改 RoomDatabase 类中的版本号。增加版本号。

于 2019-11-06T09:15:19.970 回答
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");
    }
};
于 2019-11-24T11:11:58.040 回答
1

我刚刚在浓缩咖啡测试中遇到了类似的问题,唯一解决它的是清除数据并卸载 androidx 测试 apk,例如:

adb uninstall androidx.test.orchestrator
adb uninstall androidx.test.services
于 2019-07-29T15:09:58.527 回答
0

就我而言,我正在更新一个数据库,我将与我的应用程序一起预先打包。这里的建议都没有奏效。但我终于发现我可以在数据库程序中打开 .db 文件(我使用“DB Browser for SQLite”),然后手动将“用户版本”从 2 更改回 1。之后,它运行良好。

我猜您所做的任何更新都会更改此用户版本,这就是我不断收到此错误的原因。

于 2020-03-25T01:47:19.860 回答
0

快速解决方案

转到 AddDatabase 类并增加您的数据库版本

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase

@Database(entities = arrayOf(Product::class, SatisNok::class), version = 6)
abstract class AppDatabase : RoomDatabase() {
    abstract fun productDao(): ProductDao
    abstract fun satisDao(): SatisNokDao
}

去活动或你打电话给你的地方db

添加迁移的方法,这里我把版本从5改成了6

  val MIGRATION_1_2: Migration = object : Migration(5,6) {
            override fun migrate(database: SupportSQLiteDatabase) {
                // Since we didn't alter the table, there's nothing else to do here.
            }
        }

现在将迁移添加添加到您的数据库构建器.addMigrations(MIGRATION_1_2)

 val db = Room.databaseBuilder(
                applicationContext,
                AppDatabase::class.java, "supervisor"
            ).fallbackToDestructiveMigration()
                .allowMainThreadQueries()
                .addMigrations(MIGRATION_1_2)
                .build()

有关更多详细信息,您可能希望在这里查看它日益复杂的情况,它们应该提供更简单的解决方案。

操作后,您可以在 //.addMigrations(MIGRATION_1_2) 行注释并保留下次使用

于 2021-04-07T08:37:13.380 回答
-2

我在 Codelabs 的培训计划中遇到了同样的错误。在一次培训课程中,我创建了一个项目,它成功地运行了所有数据库操作。在下一个会话中,我正在使用不同的存储库,但它是前一个项目的扩展,从扩展应用程序的第一个构建开始,我只得到了错误。

也许 Studio 保留了新版本中缺少的房间数据库的身份验证技术。

于 2019-12-12T05:20:15.673 回答