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

时间:2017-05-26 08:46:18

标签: android android-database android-room

使用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中从哪里做到这一点?

21 个答案:

答案 0 :(得分:69)

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

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

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

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

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

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

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

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

同样,如果以前的数据库模式不是在野外,则无论是递增数据库版本还是回退到破坏性迁移都是必要的。

答案 1 :(得分:11)

默认情况下,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.
//        }
//    };
}

你可以像这样实现它

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

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

答案 2 :(得分:10)

非常简单,如log

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

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

答案 3 :(得分:9)

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

搜索您已展开private static final MetricRegistry metricRegistry = new MetricRegistry(); ... Timer timer = metricRegistry.timer(name("com.codahale.metrics.servlets.MetricsServlet.registry","testval")); 的课程。你会在那里找到如下版本:

RoomDatabase

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

答案 4 :(得分: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()

有关更多详细信息,请检查official documentation

答案 5 :(得分:5)

1:-似乎我们需要更新数据库版本(增加1)

enter image description here

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

答案 6 :(得分:3)

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

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

  

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

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

答案 7 :(得分:3)

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

答案 8 :(得分:2)

在我的情况下,android:allowBackup="false"从true变为false,这也是我之前做过的噩梦,这是为什么在默认情况下启用此设置的最奇怪的事情!

答案 9 :(得分:2)

在Android手机上:

  

卸载应用清除应用数据

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

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

答案 10 :(得分:2)

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

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

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

希望它可以帮助某人。

答案 11 :(得分: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() 
}

答案 12 :(得分:2)

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

答案 13 :(得分:1)

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

希望对其他人有帮助:)

答案 14 :(得分:1)

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

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

答案 15 :(得分:1)

@Database(entities = {Tablename1.class, Tablename2.class}, version = 3, exportSchema = false)

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

答案 16 :(得分:1)

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

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

答案 17 :(得分:1)

如果您要将旧版本的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用于唯一标识每个数据库版本的身份。因此,我们需要迁移

答案 18 :(得分:0)

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

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

答案 19 :(得分:0)

快速解决方案

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

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.
            }
        }

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

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

有关更多详细信息,您可能希望查看 here 日复一日的复杂性,它们应该提供更简单的解决方案。

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

答案 20 :(得分:-2)

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

  

也许Studio通过会议室数据库保留身份验证技术   新版本缺少此功能。