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

我得到这个错误,而运行与房间数据库程序

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.

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

103934 次浏览

它非常简单,如日志所示

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,是数据库版本,你只需要增加它 一,就这样。

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

如果不增加数据库(建议) :

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

因为清除应用程序数据总是有效的,所以我每次都采用这种方法。

如果增加数据库版本:

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

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

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

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

如果您正在将 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 New Version 1.0.0-alpha9 Room 中添加了对 NOT NULL 约束的支持。

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

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

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

你可以这样做

  • 从设置中清除应用程序数据。这将从手机中删除旧的数据库(DATABASE _ VERION = 3)
  • 卸载你的应用程序
  • 将 DATABASE _ VERION 版本减少到1
  • 构建和重新安装应用程序

保持 DATABASE_VERSION恒定是一个很好的练习。

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

在我的例子中,我在迁移中使用了一个事务,而 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()
}

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

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

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

希望能帮到别人。

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

如果您更改您的模式,例如,重命名/添加/修改包含表实体的类,以前的构建中退出的 db 与新的构建之间的完整性发生冲突。

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

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

在 AndroidManifest.xml 内部,allowBackup = “ true”阻止数据在应用程序卸载后被清除。

把这个加到你的清单上:

android:allowBackup="false"

并重新安装应用程序。

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

另一个解决办法:

检查您的旧 json 文件和 apps schema 文件夹中的新 json 文件的 IdentityHash。

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

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

我在一个浓缩咖啡测试中遇到过类似的问题,唯一修复它的方法就是清除数据并卸载 androidx 测试应用程序,比如:

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

不要在生产代码中使用此解决方案!
使用 Aniruddh Parihar 的回答或者 Peterzinho16的回答代替!

在安卓手机上:

卸载 app 或 < strong > Clear app data

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

卸载(和重新安装)并不适用于所有情况,所以请先尝试清除数据!

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

enter image description here

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

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

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

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

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

我在 Codelabs 的培训项目中也犯了同样的错误。 在一次培训课程中,我创建了一个项目,并成功地运行了所有的数据库操作。 在下一个会话中,我正在处理一个不同的回购,但它是前一个项目的扩展,从第一个扩展应用程序的构建,只有我得到了错误。

也许 Studio 在房间数据库中保留了身份验证技术 新建筑缺少的东西。

在我的情况下,我正在对一个数据库进行更新,我将预先打包与我的应用程序。这里所有的建议都不管用。但我最终发现我可以打开。数据库程序中的 DB 文件(我使用“ DB Browser for SQLite”) ,并手动将“ User version”从2更改为1。在那之后,一切都很顺利。

我猜任何更新都会改变这个用户版本,这就是为什么我一直得到这个错误。

为了解决 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()

有关详细信息,请查看 正式文件

快速解决方案

转到 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()

对于更多的细节,你可能希望看看 给你它变得越来越复杂的一天,他们应该提供更容易的解决方案。

在操作之后,您可以注释//. addMigations (MIGRATION _ 1 _ 2) ,并在下次使用时保留它