You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Room数据库迁移异常:新增实体升级版本后表结构不符求助

解决Room数据库迁移后目标表未创建的问题

我来帮你梳理几个实用的排查方向,都是处理Room迁移问题时踩过的坑:

  • 先确认迁移逻辑是否正确配置
    首先检查你的RoomDatabase子类的@Database注解,有没有把新增的SuperHerosData实体加入entities数组,同时指定正确的版本号和对应的迁移类。比如:

    @Database(
        entities = [YourOldEntity::class, SuperHerosData::class],
        version = 2, // 确保版本号比旧版本高
        migrations = [MIGRATION_1_2]
    )
    abstract class AppDatabase : RoomDatabase() {
        // DAO定义
    }
    

    然后看迁移类里的SQL语句是否完全匹配预期的表结构,手动写CREATE TABLE时别漏了字段:

    val MIGRATION_1_2 = object : Migration(1, 2) {
        override fun migrate(database: SupportSQLiteDatabase) {
            database.execSQL("""
                CREATE TABLE IF NOT EXISTS `SuperHerosData` (
                    `id` INTEGER NOT NULL PRIMARY KEY,
                    `name` TEXT,
                    `realName` TEXT,
                    `team` TEXT,
                    `superFriendImage` TEXT
                )
            """.trimIndent())
        }
    }
    

    注意如果实体用了@Entity(tableName = "...")@ColumnInfo(name = "...")指定了自定义名称,SQL里的表名和列名必须和注解一致。

  • 检查实体类的注解是否正确
    确认SuperHerosData类上标注了@Entity注解,主键id@PrimaryKey配置正确(比如@PrimaryKey(autoGenerate = false)如果是手动赋值的话),每个字段的类型和注解都符合预期:

    @Entity
    data class SuperHerosData(
        @PrimaryKey val id: Int,
        val name: String?,
        val realName: String?,
        val team: String?,
        val superFriendImage: String?
    )
    

    要是某个字段需要非空约束,别忘了加@ColumnInfo(notNull = true),否则SQL里的字段会默认允许为空。

  • 排查迁移是否被正确触发

    • 先试试卸载重装APP:有时候旧的数据库文件残留会导致迁移逻辑不执行,清掉旧数据后重新运行,看新表是否正常创建。
    • 临时用fallbackToDestructiveMigration()测试:在构建数据库时添加这个方法,它会销毁旧数据库并重建新的。如果这样操作后表结构正常了,说明你的迁移逻辑肯定有问题,回到第一步仔细检查SQL语句。
  • 检查版本号是否正确升级
    别犯低级错误:确认@Database里的version值确实比之前的版本高(比如之前是1,现在必须是2或更高),而且整个项目里没有其他地方定义了冲突的版本号。

  • 查看Room的调试日志
    打开Logcat,搜索“Room”或者“SQLite”,Room会输出迁移过程的详细日志,比如SQL执行失败的原因、表结构不匹配的具体信息,这些日志能直接帮你定位到底是哪一步出了问题。

内容的提问来源于stack exchange,提问作者Sreekar Ml

火山引擎 最新活动