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方法默认运行在事务中,一旦迁移过程出现异常,所有操作会自动回滚,无需担心数据不一致问题。
后续枚举独立成表的推进思路(可选)
完成上述步骤后,可继续实现枚举迁移到新表的计划:
- 创建
EnumEntity表,存储枚举的ordinal(作为id)、枚举名称等信息。 - 批量插入所有
EnumType枚举值到新表。 - 修改
Student表,移除原enum列,将ordinal列改为外键关联EnumEntity的id。
内容的提问来源于stack exchange,提问作者Abhimanyu
相关产品推荐
相关产品推荐

