Android端SQLDelight修改表结构时如何触发回调重建数据库
SQLDelight Android端迁移回调触发规则及删库重建实现方案
回调未触发的核心原因
留空.sqm文件的操作直接导致迁移流程无法启动。SQLDelight的数据库版本号由编译插件自动根据main/sqldelight目录下的有效.sqm文件序号累加生成,空的.sqm文件不会被识别为合法迁移文件,最终设备上已存数据库的版本号会和当前App内的Schema版本号完全一致,系统判定不需要升级,自然不会执行任何回调逻辑。
AfterVersionWithDriver 回调触发场景
- 仅当设备上已安装的旧数据库版本号 < 当前App内置的
MyDatabase.Schema版本号时,SQLDelight才会启动迁移流程 - 迁移流程会按版本号从低到高依次执行对应
.sqm文件内的SQL语句,每执行完一个版本的迁移SQL,才会触发绑定了对应版本号的AfterVersionWithDriver回调:例如设备上DB版本为0,当前Schema版本为2,会先执行1.sqm、2.sqm内的迁移逻辑,执行完成后依次触发绑定的AfterVersionWithDriver(0)、AfterVersionWithDriver(1)回调 - 若缺失对应版本的
.sqm文件,SQLDelight会直接抛出迁移缺失异常,不会走到回调逻辑
表结构变更时自动删库重建的实现方法
不需要写全量表结构变更的SQL,按以下步骤配置即可:
- 每次调整表结构(新增/删除表、修改字段)后,按版本递增规则新建对应序号的
.sqm文件,例如当前最新迁移版本是2,改完结构就新建3.sqm,文件内不需要写表结构调整逻辑,加一句注释即可(比如-- trigger db recreate),保证文件非空,让编译插件正常识别、递增Schema版本号 - 替换原有回调写法,直接在升级回调里执行删表+重建逻辑,参考代码如下:
return AndroidSqliteDriver( schema = MyDatabase.Schema, context = application, name = "myDb.db", callback = object : AndroidSqliteDriver.Callback(MyDatabase.Schema) { override fun onUpgrade( db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int ) { // 清空所有业务表 db.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'") .use { cursor -> while (cursor.moveToNext()) { val tableName = cursor.getString(0) db.execSQL("DROP TABLE IF EXISTS `$tableName`") } } // 基于最新Schema重建全表 MyDatabase.Schema.create(db) } } )
如果要继续使用AfterVersionWithDriver的写法,只要保证.sqm文件非空让版本正常递增,把删表重建逻辑绑定到比当前旧版本高的对应版本回调里即可正常触发。
内容的提问来源于stack exchange,提问作者Bootstrapper
相关产品推荐
相关产品推荐

