当前位置: 首页 > news >正文

鸿蒙应用开发实战【98】— 版本迭代数据库升级实战案例

鸿蒙应用开发实战【98】— 版本迭代数据库升级实战案例

本文是「号码助手全栈开发系列」第 98 篇,持续更新中…
开源社区:https://openharmonycrossplatform.csdn.net


前言

应用上线后,数据库结构几乎必然需要随着功能迭代而变更——新增表、新增字段、修改约束。HarmonyOSrelationalStore通过版本号store.version驱动升级流程。本篇以号码助手数据库从 v1 升级到 v2 的过程为例,讲解完整的版本升级策略。

本篇涵盖:upgrade 方法设计、版本号比较逻辑、ALTER TABLE 新增字段、数据迁移与兼容性、降级保护。


一、当前数据库版本

文件features/data/DatabaseService.ets

constDB_CONFIG:relationalStore.StoreConfig={name:'number_assistant.db',securityLevel:relationalStore.SecurityLevel.S2}constDB_VERSION=1// 当前版本

二、upgrade 方法设计

privateasyncupgrade(store:relationalStore.RdbStore,fromVersion:number,toVersion:number):Promise<void>{if(fromVersion<1){// v1:初始建表(4 张表 + 索引)constddls:string[]=[`CREATE TABLE IF NOT EXISTS cards (...)`,`CREATE TABLE IF NOT EXISTS app_bindings (...)`,`CREATE TABLE IF NOT EXISTS sms_candidates (...)`,`CREATE TABLE IF NOT EXISTS sync_meta (...)`,// 索引`CREATE INDEX IF NOT EXISTS idx_ab_card ON app_bindings(card_id)`,`CREATE INDEX IF NOT EXISTS idx_ab_status ON app_bindings(status)`,`CREATE INDEX IF NOT EXISTS idx_ab_name ON app_bindings(app_name)`]for(constsqlofddls){awaitstore.executeSql(sql)}hilog.info(0x0000,TAG,'建表完成 → v1')}// 后续版本升级在这里追加// if (fromVersion < 2) { ... }// if (fromVersion < 3) { ... }}

三、v1 → v2 升级实战

假设 v2 版本需要新增两个字段:

  1. cards表增加email字段
  2. app_bindings表增加expire_at字段

3.1 升级代码

// DatabaseService.ets — upgrade 方法中追加if(fromVersion<2){constalterStatements:string[]=[// 新增 email 字段(允许为空)`ALTER TABLE cards ADD COLUMN email TEXT NOT NULL DEFAULT ''`,// 新增过期时间字段`ALTER TABLE app_bindings ADD COLUMN expire_at INTEGER NOT NULL DEFAULT 0`]for(constsqlofalterStatements){try{awaitstore.executeSql(sql)}catch(e){hilog.error(0x0000,TAG,'v2 ALTER TABLE 失败: %{public}s',JSON.stringify(e))thrownewError('数据库升级 v2 失败: '+JSON.stringify(e))}}hilog.info(0x0000,TAG,'升级完成 → v2')}

3.2 更新常量

constDB_VERSION=2// 版本号更新到 2// CardDao 中更新 COLSconstCOLS:string[]=['id','label','phone_number','carrier','remark','color','sort_order','created_at','updated_at','email'// 新增]// 更新 CardEntity 接口exportinterfaceCardEntity{// ...原有字段email?:string// 可选,兼容旧数据}

四、升级流程时序

应用启动 ↓ getRdbStore(context, config) ← 传入最新 DB_VERSION ↓ store.version != DB_VERSION? ├── 是 → upgrade(store, store.version, DB_VERSION) │ ├── fromVersion < 1 → 建表 │ ├── fromVersion < 2 → ALTER TABLE │ ├── fromVersion < 3 → ... │ └── store.version = DB_VERSION │ └── 否 → 直接使用

五、最佳实践

5.1 增量升级(非全量重建)

// ✅ 正确:每个版本增量变更if(fromVersion<2){/* ALTER TABLE v1→v2 */}if(fromVersion<3){/* ALTER TABLE v2→v3 */}// ❌ 错误:每次重建(会丢失数据)// await store.executeSql('DROP TABLE IF EXISTS cards')// 重新建表...(不要这样做)

5.2 ALTER TABLE 支持的操作

操作SQL支持风险等级
新增列ALTER TABLE t ADD COLUMN c TYPE🟢 低
重命名列ALTER TABLE t RENAME COLUMN old TO new✅ (HarmonyOS 6.1+)🟡 中
删除列ALTER TABLE t DROP COLUMN c❌ 部分版本不支持🔴 高
修改默认值无法直接修改需创建新表迁移🔴 高
新增索引CREATE INDEX🟢 低

5.3 数据迁移(复杂变更)

当需要合并/拆分列时,无法用简单 ALTER TABLE 完成:

if(fromVersion<2){// 1. 创建新表awaitstore.executeSql(`CREATE TABLE cards_new ( id INTEGER PRIMARY KEY AUTOINCREMENT, display_name TEXT NOT NULL DEFAULT '' )`)// 2. 迁移数据(将 label + phone_number 合并为 display_name)awaitstore.executeSql(`INSERT INTO cards_new (id, display_name) SELECT id, label || ' - ' || phone_number FROM cards`)// 3. 删除旧表awaitstore.executeSql('DROP TABLE cards')// 4. 重命名新表awaitstore.executeSql('ALTER TABLE cards_new RENAME TO cards')}

5.4 防御性检查

// 每次 ALTER TABLE 前检查列是否存在,避免重复执行consthasColumn=awaitthis.columnExists(store,'cards','email')if(!hasColumn){awaitstore.executeSql('ALTER TABLE cards ADD COLUMN email TEXT NOT NULL DEFAULT ""')}privateasynccolumnExists(store:relationalStore.RdbStore,table:string,columnName:string):Promise<boolean>{try{constrs=awaitstore.executeSql(`PRAGMA table_info(${table})`)// 遍历 ResultSet 检查 columnNamewhile(rs.goToNextRow()){if(rs.getString(1)===columnName)returntrue}returnfalse}catch{returnfalse}}

六、降级保护

如果用户安装的是旧版本应用打开新版数据库:

privateasyncupgrade(...){// 降级保护:fromVersion 大于 toVersionif(fromVersion>toVersion){hilog.warn(0x0000,TAG,'数据库版本 %{public}d > 应用版本 %{public}d,降级',fromVersion,toVersion)// 可以选择重新创建或报错thrownewError('数据库不兼容:请先升级应用')}// ...}

七、版本升级检查清单

版本变更内容SQL
v1初始建表(4 表 + 3 索引)CREATE TABLE
v2cards 新增 email、bindings 新增 expire_atALTER TABLE ADD COLUMN
v3合并字段(示例)新建表 + INSERT + DROP + RENAME

小结

概念要点
版本驱动store.versionDB_VERSION比较触发 upgrade
增量升级每个版本独立 if 块,不破坏旧版本
ALTER TABLE主要用 ADD COLUMN,复杂变更用建新表 + 迁移
防御性检查列是否存在、降级保护、事务包裹
兼容旧数据新字段用 DEFAULT 值,新接口参数用可选?

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

  • 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
  • HarmonyOS relationalStore 开发指南:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/data-persistence-by-rdb
  • HarmonyOS 官方文档:https://developer.huawei.com/consumer/cn/doc/
  • HarmonyOS hilog文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/hilog
  • HarmonyOS testing:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/unit-test
  • HarmonyOS 安全与权限:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/permissions-overview
http://www.jsqmd.com/news/1205710/

相关文章:

  • 2026年沈阳防静电地板厂家挑选攻略 森塞尔及行业信息汇总 - 资讯在线
  • GPT-5.6 Sol硬件诊断实战:MacBook电源问题调试与安全防护
  • Hy-Embodied-VLM-1.0未来展望:具身智能的发展趋势与技术挑战
  • SQL Server错误号解析与数据库故障处理指南
  • 为什么 DPDK VirtIO 只能跑到 40Gbps?—— 一次 KVM 虚拟交换机性能瓶颈定位全过程(下)
  • 延续抽象副作用:Gleam 中延续的应用及业务逻辑抽象实现
  • 解决华为eNSP与VirtualBox在Win11上的兼容性问题
  • 2026螺旋板式换热器怎么选不踩雷?优质厂家实力排名 全工况选购攻略 - 资讯在线
  • TrollInstallerX终极教程:3分钟搞定iOS 14-16.6.1 TrollStore安装的完整指南
  • Dify平台:AI应用开发与RAG技术实践指南
  • AI解决数学难题?拆解GPT模型能力边界与验证方法
  • C++ string进阶:find、substr与关系运算符实战解析
  • 如何轻松管理游戏DLSS版本:玩家必备的智能工具终极指南
  • 2026在广州怎么高价出手闲置奢侈品?速看这篇回收门店测评! - 全国二奢机构参考
  • 解决Windows磁盘8MB空间无法删除的终极方案
  • wild-wild-path vs 其他路径工具:为什么它是处理复杂对象的最佳选择
  • Phigros高难度谱面操作分析:从珍贵录像中提取音游进阶技巧
  • 基于大数据的亚健康人群的分析系统的设计与实现
  • CW32开发板ADC电压采集与优化实践
  • AI代码审查工具altimate-code:原理、部署与实战集成指南
  • 5分钟解决Unity游戏插件加载难题:BepInEx完全指南
  • 2026年沈阳空乘艺考培训挑选攻略 博冠国际教育等机构服务梳理 - 资讯在线
  • 【软考备考】流水线计算详解:吞吐率、加速比、效率,看懂时空图就不用背公式(附 10 道练习)
  • XbsjEarthUI开发模式对比:dev vs dev2 vs build模式深度解析
  • AwesomeSplash适配指南:多分辨率、多版本Android系统的兼容性处理
  • LSP Plugins性能优化:如何获得最佳音频处理性能的10个技巧
  • 5分钟上手mini-coder-4b-OptiQ-4bit:Python代码生成实例教程
  • Claude提示词工程:从CRAM原则到高效模板实战
  • Solod:让 Go 代码无缝转换为 C 代码,零运行时开销带来新编程体验!
  • 移动新闻客户端个性化推荐系统