Android Room预填充数据库迁移:保留数据并新增行列方案
解决Room数据库迁移:保留原有数据+新增列和行的方案
看起来你遇到的核心问题是既要保留原有isAlive的状态,又要完成新增strength列(且所有15条数据值唯一)和插入5条新数据的迁移需求,之前的两种方案要么丢失数据,要么没完成全部操作。我来给你一步步梳理正确的实现方式:
1. 修正迁移版本号(关键!)
你之前写的Migration(2, 3)是错误的——如果你的初始数据库版本是1,现在要升级到版本2,迁移的起始和目标版本应该是(1, 2)。这个错误会导致Room识别不到迁移规则,直接触发 fallback 或者忽略迁移逻辑。
2. 编写完整的迁移逻辑
在migrate方法里,我们需要分三步完成所有需求:
- 新增
strength列(先给原有数据一个默认值,后续再更新为唯一值) - 更新原有10条数据的
strength为不同数值 - 插入5条新数据,确保它们的
strength和原有数据不重复
完整的迁移代码如下:
val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { // 步骤1:添加strength列,默认值0(保证原有数据都有有效值) database.execSQL("ALTER TABLE user ADD COLUMN strength INTEGER NOT NULL DEFAULT 0") // 步骤2:更新原有10条数据的strength为1-10(确保唯一,假设原有数据id是1到10) for (id in 1..10) { database.execSQL( "UPDATE user SET strength = ? WHERE id = ?", arrayOf(id, id) ) } // 步骤3:插入5条新数据,strength设为11-15(和原有数据不重复) val newUserData = listOf( ("New User 1", true, 11), ("New User 2", false, 12), ("New User 3", true, 13), ("New User 4", false, 14), ("New User 5", true, 15) ) newUserData.forEach { (name, isAlive, strength) -> database.execSQL( "INSERT INTO user (name, isAlive, strength) VALUES (?, ?, ?)", arrayOf(name, isAlive, strength) ) } } }
3. 更新数据库版本并应用迁移
在你的AppDatabase类的@Database注解里,把version从1改成2,并且把迁移规则加入到数据库构建器中:
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db") .addMigrations(MIGRATION_1_2) .build()
关键注意事项
- 如果原有数据的
id不是1到10,需要调整UPDATE语句的匹配条件(比如用其他唯一标识字段),确保每条原有数据都被分配到唯一的strength值。 - 绝对不要启用
fallbackToDestructiveMigration(),否则会直接删除旧数据库重建,丢失所有isAlive的状态。 - 新增数据的
name和isAlive值可以根据你的实际需求调整,只要保证strength和原有数据不重复即可。
这样执行迁移后,原有10条数据的isAlive状态会被完整保留,所有15条数据的strength值都是唯一的,同时也成功新增了5条数据。
内容的提问来源于stack exchange,提问作者Ashutosh Kailkhura
相关产品推荐
相关产品推荐

