预打包的数据库在 Room Android kotlin 中具有无效的架构

Pre-packaged database has an invalid schema in Room Android kotlin

提问人:Sabuj Ahmed 提问时间:11/17/2023 最后编辑:HilleSabuj Ahmed 更新时间:11/17/2023 访问量:39

问:

我正在尝试从资产文件夹 SQL DB 获取数据,但出现以下错误:

java.lang.IllegalStateException: Pre-packaged database has an invalid schema: recipetype(com.example.finddishrecipe.room.RecipeEntity).
Expected:
TableInfo{name='recipetype', columns={name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, image=Column{name='image', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='recipetype', columns={id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='undefined'}, name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, image=Column{name='image', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}}, foreignKeys=[], indices=[]}

这是我的实体代码:

@Entity(tableName = "recipetype")

data class RecipeEntity(
    @PrimaryKey

    @ColumnInfo(name = "id")
    val id: Int,

    @ColumnInfo(name = "name")
    val name: String,

    @ColumnInfo(name = "image")
    val image: String
)
android kotlin android-studio android-room 数据库迁移

评论

0赞 Ariczek 11/17/2023
stackoverflow.com/a/71960555/20755786 - 假设资产文件中列的顺序,也请提供。
0赞 Sabuj Ahmed 11/17/2023
CREATE TABLE “recipetype” ( “id” INTEGER, “name” TEXT, “image” TEXT, PRIMARY KEY(“id” AUTOINCREMENT) )

答:

0赞 Varsha Kulkarni 11/17/2023 #1

根据预期的架构,所有列都应该具有非 null 约束。在创建表时,通过添加约束将它们定义为非 null 值,如下所示:NOT NULL

CREATE TABLE "recipetype" ( "id" INTEGER NOT NULL, "name" TEXT NOT NULL, "image" TEXT NOT NULL, PRIMARY KEY("id" AUTOINCREMENT) )

或者,可以将实体类列设置为可为 null 的对象。

列的顺序应该无关紧要。

0赞 MikeT 11/17/2023 #2

确保预打包的数据库与 Room 期望的数据库相匹配的最简单方法是:-

  1. 创建带注释的类,然后@Entity
  2. 将带注解的类(抽象)与注解的 entities 参数中定义的带注解的类相加,然后@Database@Entity@Database
  3. 成功编译项目 (CTRL +F9)。
  4. 使用 Android 视图找到 java(generated) 文件夹,然后
  5. 找到与带注释的类同名但后缀为 Impl 的类,然后@Database
  6. 找到 createAllTables 方法,然后针对每个表(带注释的类)@Entity
  7. 复制 Room 为表生成的 SQL,以在您正在使用的 SQLite 工具中创建表。
    1. 这个 SQL 正是 Room 所期望的,因此没有必要尝试预测 Room 的底层规则。
  • 注意忽略room_master表,房间将处理它的创建
  • 如果需要,也可以相应地创建其他组件,例如视图和索引。

如果你有一个相对接近的现有数据库,那么你可以使用SQLite工具转换定义,如下所示:

  1. ALTER the existing table(s) to RENAME it(them)。
  2. 使用生成的 java 中的 SQL 创建实际表。
  3. 使用重命名的原始表将数据加载到新创建的实际表中(通常,这可能就像相应地命名表名一样简单)INSERT INTO actual_table SELECT * FROM renamed_existing_table
  4. (可选)删除重命名的表
  5. (可选)对数据库进行 VACUUM 操作(以释放未使用的页面)

或者,您可以使用 PrePackagedDatabase 回调的 overidden 方法转换数据库,在复制资产时采用类似的方法转换表。onOpen