提问人:Sabuj Ahmed 提问时间:11/17/2023 最后编辑:HilleSabuj Ahmed 更新时间:11/17/2023 访问量:39
预打包的数据库在 Room Android kotlin 中具有无效的架构
Pre-packaged database has an invalid schema in Room Android kotlin
问:
我正在尝试从资产文件夹 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
)
答:
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 期望的数据库相匹配的最简单方法是:-
- 创建带注释的类,然后
@Entity
- 将带注解的类(抽象)与注解的 entities 参数中定义的带注解的类相加,然后
@Database
@Entity
@Database
- 成功编译项目 (CTRL +F9)。
- 使用 Android 视图找到 java(generated) 文件夹,然后
- 找到与带注释的类同名但后缀为 Impl 的类,然后
@Database
- 找到 createAllTables 方法,然后针对每个表(带注释的类)
@Entity
- 复制 Room 为表生成的 SQL,以在您正在使用的 SQLite 工具中创建表。
- 这个 SQL 正是 Room 所期望的,因此没有必要尝试预测 Room 的底层规则。
- 注意忽略room_master表,房间将处理它的创建
- 如果需要,也可以相应地创建其他组件,例如视图和索引。
如果你有一个相对接近的现有数据库,那么你可以使用SQLite工具转换定义,如下所示:
- ALTER the existing table(s) to RENAME it(them)。
- 使用生成的 java 中的 SQL 创建实际表。
- 使用重命名的原始表将数据加载到新创建的实际表中(通常,这可能就像相应地命名表名一样简单)
INSERT INTO actual_table SELECT * FROM renamed_existing_table
- (可选)删除重命名的表
- (可选)对数据库进行 VACUUM 操作(以释放未使用的页面)
或者,您可以使用 PrePackagedDatabase 回调的 overidden 方法转换数据库,在复制资产时采用类似的方法转换表。onOpen
- 与此答案相似 使用带有空间的压缩预填充数据库
评论