Android Kotlin上线项目合并双Room数据库的迁移方案问询
合并上线项目中两个Room数据库的迁移方案
1. 先规划新数据库结构
- 梳理DB1和DB2的所有实体(Entity),合并重复表结构,统一命名避免冲突(比如两个模块都有
User表时,要确定字段取舍、数据合并规则)。 - 定义新的
Room Database类,包含所有合并后的实体,设置新的数据库名称(比如CombinedDB)和初始版本号(建议基于两个旧库的最高版本+1,或者直接设为1——因为这是全新库,后续按常规规则升级)。
2. 保留旧库定义,实现跨库数据迁移
由于项目已上线,用户设备上同时存在DB1和DB2,不能直接删除旧库,得先读取旧库数据写入新库,完成后再清理旧库:
- 复制旧库的核心类到新模块:把旧Module1、Module2中的Room实体、DAO、Database类完整复制到合并后的模块中,必须保证旧库的Database类的
name参数、实体字段、版本号和线上版本完全一致,这样Room才能找到设备上已存在的旧数据库文件。
示例旧DB1的Database类:@Database(entities = [DB1User::class, DB1Order::class], version = 3) abstract class DB1 : RoomDatabase() { abstract fun db1UserDao(): DB1UserDao abstract fun db1OrderDao(): DB1OrderDao } - 编写数据迁移工具:创建一个工具类,负责读取旧库数据、转换为新库实体、写入新库:
object DBDataMigrator { suspend fun migrateToCombinedDB(context: Context) { // 初始化旧库实例(fallbackToDestructiveMigration避免旧库版本变化导致的初始化失败) val db1 = Room.databaseBuilder(context, DB1::class.java, "db1_name") .fallbackToDestructiveMigration() .build() val db2 = Room.databaseBuilder(context, DB2::class.java, "db2_name") .fallbackToDestructiveMigration() .build() // 读取旧库数据 val db1Users = db1.db1UserDao().getAllUsers() val db2Products = db2.db2ProductDao().getAllProducts() // 转换为新库实体(处理字段映射、重复数据合并) val combinedUsers = db1Users.map { it.toCombinedUser() } val combinedProducts = db2Products.map { it.toCombinedProduct() } // 写入新库 val combinedDB = Room.databaseBuilder(context, CombinedDB::class.java, "combined_db") .build() combinedDB.runInTransaction { combinedDB.combinedUserDao().insertAll(combinedUsers) combinedDB.combinedProductDao().insertAll(combinedProducts) } // 清理旧库 db1.close() db2.close() context.deleteDatabase("db1_name") context.deleteDatabase("db2_name") } }
3. 控制迁移执行时机
- 在App启动阶段(比如
Application的onCreate或主页面onCreate),检查旧库是否存在、新库是否已初始化,满足条件则在后台线程执行迁移:class MyApp : Application() { override fun onCreate() { super.onCreate() CoroutineScope(Dispatchers.IO).launch { val hasOldDBs = databaseList().contains("db1_name") || databaseList().contains("db2_name") val hasCombinedDB = databaseList().contains("combined_db") if (hasOldDBs && !hasCombinedDB) { DBDataMigrator.migrateToCombinedDB(this@MyApp) } } } }
4. 处理边缘场景
- 重复数据冲突:如果两个旧库有同业务的表(比如都有
User),提前定好合并规则——比如保留DB1的数据、合并字段(取最新更新时间的记录),或让用户手动选择。 - 迁移失败回滚:迁移前备份旧库文件,一旦迁移失败,恢复旧库避免数据丢失。
- 多版本兼容:如果旧库有多个历史版本,确保复制的旧Database类能兼容所有旧版本,或在读取时处理不同版本的字段差异。
- 全场景测试:覆盖仅装过Module1、仅装过Module2、同时装过两个模块、全新安装的用户场景,确保迁移逻辑稳定。
5. 后续版本维护
- 迁移完成后,新数据库的版本更新按常规Room迁移流程处理(编写
Migration类,添加到databaseBuilder)。 - 几个版本后,确认所有用户都完成迁移,可移除旧库的实体、Database类和迁移代码。
内容的提问来源于stack exchange,提问作者gourav anand
相关产品推荐
相关产品推荐

