如何为ObjectBox预填充数据库执行数据与Schema迁移?
1 数据库迁移的具体处理流程
ObjectBox本身内置了Schema版本校验和迁移机制,结合你预填充data.mdb的场景,完整流程如下:
- 每次修改实体类(增删字段、新增/删除实体、调整字段属性)后,运行
dart run build_runner build生成最新的objectbox-model.json文件,该文件会自动记录当前的Schema版本号 - 安装应用时你把预填充的
.mdb文件复制到应用的ObjectBox指定目录后,第一次初始化ObjectBox时,框架会自动读取现有数据库的Schema版本,和当前代码对应的objectbox-model.json里的版本做比对 - 如果现有版本等于当前版本:直接启动数据库,无需额外操作
- 如果现有版本低于当前版本:触发迁移流程,默认会自动处理新增可空字段、删除实体/字段这类无歧义的Schema变更;如果涉及字段重命名、字段类型调整、旧数据格式转换等需要业务逻辑介入的变更,就走自定义迁移逻辑
- 迁移完成后框架会自动更新数据库的Schema版本号,再对外开放数据库操作能力
2 兼容数据+Schema迁移的架构设计
要实现和Realm类似的迁移能力,你可以按如下分层搭建架构,和业务代码完全解耦:
- 首先单独封装
ObjectBoxMigrationManager迁移管理类,所有迁移逻辑都收敛在这个类里- 版本配置层:统一管理所有历史Schema版本常量,避免硬编码,示例:
class ObjectBoxMigrationConfig { static const int v1 = 1; static const int v2 = 2; static const int v3 = 3; static const int latestVersion = v3; } - 迁移逻辑层:每个版本的迁移对应独立的方法,比如
_migrateV1ToV2(Store store)、_migrateV2ToV3(Store store),方法内同时处理Schema适配和对应的数据转换逻辑 - 触发入口层:在
openStore初始化时传入onUpgrade回调,回调中调用迁移管理类的处理方法
- 版本配置层:统一管理所有历史Schema版本常量,避免硬编码,示例:
- 额外适配你预填充数据库的场景:每次打包发版前,确保你打包进去的预填充
.mdb文件的Schema版本和当前代码的版本对应,如果预填充的是旧版本库,第一次启动会自动触发迁移,无需额外处理
3 分版本增量迁移的实现
完全可以实现你描述的逐版本增量迁移逻辑,ObjectBox的onUpgrade回调本身就是为这种场景设计的,推荐用循环判断适配跨版本升级的场景,示例代码如下:
final store = await openStore( onUpgrade: (store, oldVersion, newVersion) async { var currentVer = oldVersion; // 逐版本迁移,支持直接跨多个大版本升级 while (currentVer < newVersion) { switch (currentVer) { case 0: // 处理v0到v1的迁移逻辑,示例:给新增非空字段赋值、迁移旧字段数据到新字段 final userBox = store.box<User>(); final allUsers = userBox.getAll(); for (var user in allUsers) { user.newNickname = user.oldName ?? '匿名用户'; } userBox.putMany(allUsers); currentVer++; break; case 1: // 处理v1到v2的迁移逻辑,示例:调整字段格式、删除无效数据 currentVer++; break; // 后续新版本只需新增case即可 } } } );
注意点:如果涉及字段重命名场景,需要给对应字段加
@Uid()注解保留旧字段的唯一标识,避免ObjectBox将旧字段判定为删除、新字段判定为新增导致数据丢失。
内容的提问来源于stack exchange,提问作者Dev Loots
相关产品推荐
相关产品推荐

