You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Room迁移:如何在migrate方法中读写现有数据?

Room数据库迁移:新增枚举ordinal列并填充数据

步骤1:修改Student实体类

更新你的Student数据类,新增ordinal字段(如果需要自定义列名可添加@ColumnInfo注解):

data class Student(
    @PrimaryKey val id: Long, // 假设表中存在主键id
    val enum: EnumType,
    val ordinal: Int,
    // 其他字段...
)

步骤2:实现Migration迁移逻辑

在Room的Migration类中分两步操作:先新增列,再批量更新数据填充ordinal值:

val MIGRATION_OLD_TO_NEW = object : Migration(旧版本号, 新版本号) {
    override fun migrate(database: SupportSQLiteDatabase) {
        // 1. 新增ordinal列,设置默认值避免非空约束报错
        database.execSQL("ALTER TABLE Student ADD COLUMN ordinal INTEGER NOT NULL DEFAULT 0;")
        
        // 2. 查询所有Student数据,将enum对应的ordinal写入新列
        val cursor = database.query("SELECT id, enum FROM Student")
        while (cursor.moveToNext()) {
            val studentId = cursor.getLong(cursor.getColumnIndexOrThrow("id"))
            val enumStr = cursor.getString(cursor.getColumnIndexOrThrow("enum"))
            
            // 将数据库存储的枚举字符串转为EnumType实例,获取ordinal值
            val enumValue = EnumType.valueOf(enumStr)
            val ordinalValue = enumValue.ordinal
            
            // 更新当前Student的ordinal列
            database.execSQL(
                "UPDATE Student SET ordinal = ? WHERE id = ?;",
                arrayOf(ordinalValue, studentId)
            )
        }
        cursor.close()
    }
}

关键注意事项

  • 确保EnumType的枚举名称和数据库中enum列存储的字符串完全匹配,否则valueOf会抛出异常;若存在历史数据不兼容的情况,建议提前做兼容处理(比如添加兜底的默认枚举值)。
  • 如果Student表没有id主键,可以用其他唯一标识字段作为更新条件,保证每条数据能被精准定位。
  • Room的migrate方法默认运行在事务中,一旦迁移过程出现异常,所有操作会自动回滚,无需担心数据不一致问题。

后续枚举独立成表的推进思路(可选)

完成上述步骤后,可继续实现枚举迁移到新表的计划:

  1. 创建EnumEntity表,存储枚举的ordinal(作为id)、枚举名称等信息。
  2. 批量插入所有EnumType枚举值到新表。
  3. 修改Student表,移除原enum列,将ordinal列改为外键关联EnumEntity的id。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 01:24:29