Room数据库迁移报错:添加deleted列后约束预期与实际不符
解决Room实体嵌套后的迁移报错问题
嘿,我来帮你排查这个问题!你遇到的这个「预期deleted列notNull为false,实际为true」的错误,核心原因是Room根据实体类生成的预期数据库结构,和你手动执行SQL后的实际结构不匹配。咱们一步步来解决:
1. 先检查实体类的定义是否正确
首先要确保你的PackageModel实体里的deleted字段,和你期望的数据库约束完全一致:
@Entity(tableName = "PackageModel") data class PackageModel( // 其他原有字段... @ColumnInfo( name = "deleted", nullable = false, // 明确标记非空 defaultValue = "0" // 设置默认值 ) val deleted: Int = 0 // 用非空类型Int,而不是Int? )
因为DeliveryJsonModel通过@Embedded嵌入了PackageModel,Room会自动把PackageModel的字段映射到DeliveryJsonModel对应的表中。这里要注意:
- 如果你的
@Embedded设置了prefix(比如@Embedded(prefix = "pkg_")),那你迁移语句里的列名应该是pkg_deleted,而不是deleted,别搞混了! - 不要在
DeliveryJsonModel里手动定义deleted字段,否则会和嵌入的字段冲突。
2. 为什么会出现notNull不匹配的报错?
Room会根据你的实体类代码生成「预期的数据库schema」,然后和实际数据库的结构对比。报错说明:
- Room从实体类解析出的
deleted字段是允许为null的(notNull=false) - 但你通过
ALTER TABLE语句添加的是非空列(notNull=true)
这时候你要对应调整:
方案A:让实体类和SQL保持一致(推荐)
如果你的业务逻辑要求deleted是非空的,那就按上面的代码修正PackageModel的deleted字段,确保它是非空类型+标注nullable=false。这样Room生成的预期schema里,deleted的notNull就是true,和你SQL里的约束匹配。
方案B:调整SQL匹配实体类(不推荐,除非业务允许)
如果你的实体类里deleted是可空类型(比如Int?),那你需要把迁移语句改成允许null:
ALTER TABLE DeliveryJsonModel ADD COLUMN deleted INTEGER DEFAULT 0
(去掉NOT NULL关键字)
3. 清理构建缓存,确保Room更新schema
有时候Android Studio的构建缓存会导致Room没有正确解析实体类的最新改动,这时候你需要:
- 点击顶部菜单栏的
Build -> Clean Project - 然后点击
Build -> Rebuild Project - 可以去
app/src/main/schemas/你的包名/数据库版本号.json文件里,确认DeliveryJsonModel表中的deleted字段的notNull值是否为true(如果你用的是方案A)
做完这些再重新运行迁移,应该就能解决报错了。
内容的提问来源于stack exchange,提问作者The Bat
相关产品推荐
相关产品推荐

