Room 无法验证从具有索引的资产构建的数据库的数据完整性
Room cannot verify data integraty of database built from asset with indices
总结
我正在用 createFromAsset()
预填充一个数据库它可以工作,现在我需要向数据库添加索引,但是 Room 无法处理此更改。
快记
此数据库未投入生产,我在进行更改后重新安装了应用程序,我的问题不是关于如何从版本 X 迁移到 Y 的常见问题。
代码
这是我的实体
@Entity(tableName = "myTable", indices = [Index(value = ["col1","col2"], name = "myIndex")])
...
我运行下面的查询也将索引添加到预填充的数据库
CREATE INDEX myIndex ON myTable (col1,col2)
进行这些更改后,我重新安装了应用程序以避免数据库版本问题。
问题是 Room 总是无法验证数据完整性,增加版本不是一个选项,如果(且仅当)我先安装版本 1 然后增加版本,它确实可以解决问题。
迁移也必须为空才能工作,执行以下查询失败,因为 myIndex
已经存在:
db.execSQL("CREATE INDEX myIndex ON myTable (col1,col2)")
我试过的
- 运行
onCreate
中的本地查询来自 RoomDatabase.Callback()
,而不是直接从资产中导入。
想知道...
我似乎不明白为什么 Room 抱怨索引,它拒绝添加它,因为它已经存在,运行空迁移解决了问题,而不是 运行任何迁移给了我一个验证异常。
问题是我不能 运行 空迁移只是为了修复它,因为迁移根本不会 运行 因为这个数据库还没有投入生产。
我感到迷茫。
it refuses to add it because it already exists,
使用CREATE INDEX IF NOT EXISTS myIndex ON myTable (col1,col2)
您应该在 onOpen
函数中使用它。
或者,如果使用 Room 2.4.0-beta2 或更高版本,则有一个 prePackagedDatabase
回调,您可以使用它执行相同的操作,但仅当预打包数据库被复制时。
每次数据库 built/opened 时都会调用 onOpen
函数(这不是问题,因为现有的索引会导致最小的开销)。
而仅当数据库来自资产 created/copied 时才会调用 prePackagedDatabase 回调。
onCreate
函数仅在 Room 创建数据库时 运行s。使用 createFromAsset(或文件)时,它不会创建数据库。但是,如果您使用 fallbackToDestructiveMigration 并且没有涵盖 from/to 版本的迁移,则会调用 onCreate
。
正确的解决方案是将索引包含在预打包数据库中,这样它就会一直存在。
I can't seem to understand why Room complains about the indice, it refuses to add it because it already exists, running an empty migration fixes the problem, not running any migration gives me a verification exception.
如果您 运行 全新安装,那么当索引在实体中定义时,它将创建索引。因此它已经存在的原因(如果它已经存在,则 IF NOT EXISTS 不会创建它)。
Not 运行迁移失败,因为空间根据实体生成 identity_hash。更改实体和房间看到身份哈希已更改。
您可能会发现查看生成的 java(从 Android Studio 中的 Android 视图可见)寻找 class 即 class 用 @Database 注释但带有 _Impl 后缀并在 class 中查找 createAllTables 方法。这包括 Room 将创建的所有 table 和索引。
您会看到 room_master table 包含与包中的 identity_hash 进行比较的 identity_hash。您还会看到 Room 在所有 CREATE 语句中都包含 IF NOT EXISTS
。
总结
我正在用 createFromAsset()
预填充一个数据库它可以工作,现在我需要向数据库添加索引,但是 Room 无法处理此更改。
快记
此数据库未投入生产,我在进行更改后重新安装了应用程序,我的问题不是关于如何从版本 X 迁移到 Y 的常见问题。
代码
这是我的实体
@Entity(tableName = "myTable", indices = [Index(value = ["col1","col2"], name = "myIndex")])
...
我运行下面的查询也将索引添加到预填充的数据库
CREATE INDEX myIndex ON myTable (col1,col2)
进行这些更改后,我重新安装了应用程序以避免数据库版本问题。
问题是 Room 总是无法验证数据完整性,增加版本不是一个选项,如果(且仅当)我先安装版本 1 然后增加版本,它确实可以解决问题。
迁移也必须为空才能工作,执行以下查询失败,因为 myIndex
已经存在:
db.execSQL("CREATE INDEX myIndex ON myTable (col1,col2)")
我试过的
- 运行
onCreate
中的本地查询来自RoomDatabase.Callback()
,而不是直接从资产中导入。
想知道...
我似乎不明白为什么 Room 抱怨索引,它拒绝添加它,因为它已经存在,运行空迁移解决了问题,而不是 运行任何迁移给了我一个验证异常。
问题是我不能 运行 空迁移只是为了修复它,因为迁移根本不会 运行 因为这个数据库还没有投入生产。
我感到迷茫。
it refuses to add it because it already exists,
使用CREATE INDEX IF NOT EXISTS myIndex ON myTable (col1,col2)
您应该在 onOpen
函数中使用它。
或者,如果使用 Room 2.4.0-beta2 或更高版本,则有一个 prePackagedDatabase
回调,您可以使用它执行相同的操作,但仅当预打包数据库被复制时。
每次数据库 built/opened 时都会调用
onOpen
函数(这不是问题,因为现有的索引会导致最小的开销)。而仅当数据库来自资产 created/copied 时才会调用 prePackagedDatabase 回调。
onCreate
函数仅在 Room 创建数据库时 运行s。使用 createFromAsset(或文件)时,它不会创建数据库。但是,如果您使用 fallbackToDestructiveMigration 并且没有涵盖 from/to 版本的迁移,则会调用onCreate
。
正确的解决方案是将索引包含在预打包数据库中,这样它就会一直存在。
I can't seem to understand why Room complains about the indice, it refuses to add it because it already exists, running an empty migration fixes the problem, not running any migration gives me a verification exception.
如果您 运行 全新安装,那么当索引在实体中定义时,它将创建索引。因此它已经存在的原因(如果它已经存在,则 IF NOT EXISTS 不会创建它)。
Not 运行迁移失败,因为空间根据实体生成 identity_hash。更改实体和房间看到身份哈希已更改。
您可能会发现查看生成的 java(从 Android Studio 中的 Android 视图可见)寻找 class 即 class 用 @Database 注释但带有 _Impl 后缀并在 class 中查找 createAllTables 方法。这包括 Room 将创建的所有 table 和索引。
您会看到 room_master table 包含与包中的 identity_hash 进行比较的 identity_hash。您还会看到 Room 在所有 CREATE 语句中都包含 IF NOT EXISTS
。