基于HarmonyOS的情侣美食管理应用开发实战(五)- 数据持久化问题修复

📖 系列文章目录

  • (一)项目设计与角色管理
  • (二)菜谱管理与订单系统
  • (三)美食相册与设置功能
  • (四)数据库优化与问题解决
  • (五)数据持久化问题修复(本文)
  • (六)图片显示问题修复

一、问题发现

1.1 问题现象

在测试情侣美食管理应用时,发现了一个严重的问题:

用户操作流程:

  1. 打开应用,添加菜谱"凉拌猪耳朵"
  2. 填写菜谱信息,上传图片
  3. 保存成功,菜谱出现在列表中
  4. 关闭应用(完全退出)
  5. 重新打开应用

预期结果:

  • 菜谱"凉拌猪耳朵"应该还在列表中
  • 图片应该正常显示

实际结果:

  • ❌ 菜谱列表为空
  • ❌ 所有数据丢失
  • ❌ 需要重新添加菜谱
    在这里插入图片描述

1.2 问题影响

这个问题严重影响应用的使用价值:

  • 用户辛苦添加的菜谱无法保存
  • 无法积累菜谱库
  • 应用失去了实际意义

二、问题定位

2.1 初步排查

首先检查数据库相关代码,查看 RdbUtil.ets 的初始化方法:

static async init(context: Context): Promise<void> {
  LogUtil.info(RdbUtil.TAG, '开始初始化数据库')
  
  // 删除旧数据库强制重建(开发阶段)
  try {
    await relationalStore.deleteRdbStore(context, CommonConstant.DB_NAME)
    LogUtil.info(RdbUtil.TAG, '已删除旧数据库,将重新创建')
  } catch (err) {
    LogUtil.info(RdbUtil.TAG, '数据库不存在或删除失败,继续创建新数据库')
  }
  
  // 创建数据库配置
  const config: relationalStore.StoreConfig = {
    name: CommonConstant.DB_NAME,
    securityLevel: relationalStore.SecurityLevel.S1
  }
  
  // 创建数据库
  RdbUtil.rdbStore = await relationalStore.getRdbStore(context, config)
  
  // 创建表结构
  await RdbUtil.createTables()
  
  LogUtil.info(RdbUtil.TAG, '数据库初始化完成')
}

2.2 问题分析

发现问题:
代码中有一段删除数据库的逻辑:

await relationalStore.deleteRdbStore(context, CommonConstant.DB_NAME)

问题原因:

  1. 开发阶段的遗留代码

    • 开发时为了快速迭代,每次都删除旧数据库
    • 便于测试表结构变更
  2. 忘记移除

    • 发布时忘记移除这段代码
    • 导致每次启动都会删除数据库
  3. 执行流程

    • 应用启动 → RdbUtil.init()
    • 删除旧数据库 → 所有数据丢失
    • 创建新数据库 → 空数据库
    • 结果:数据无法持久化

三、解决方案

3.1 修复代码

移除删除数据库的逻辑,直接使用 getRdbStore

static async init(context: Context): Promise<void> {
  LogUtil.info(RdbUtil.TAG, '开始初始化数据库')
  
  // 数据库配置
  const config: relationalStore.StoreConfig = {
    name: CommonConstant.DB_NAME,
    securityLevel: relationalStore.SecurityLevel.S1
  }
  
  // 获取数据库实例(如果不存在会自动创建)
  RdbUtil.rdbStore = await relationalStore.getRdbStore(context, config)
  
  // 创建表结构
  await RdbUtil.createTables()
  
  LogUtil.info(RdbUtil.TAG, '数据库初始化完成')
}

3.2 关键改动

改动说明:

  • ✅ 移除了 deleteRdbStore 的调用
  • ✅ 直接使用 getRdbStore 获取数据库实例
  • ✅ 系统会自动判断数据库是否存在
  • ✅ 不存在则创建,存在则打开

API说明:

// getRdbStore 的行为:
// - 如果数据库不存在,自动创建并返回
// - 如果数据库已存在,直接打开并返回
// - 不会删除已有数据

3.3 数据库文件位置

数据库文件保存在应用私有目录:

/data/app/el2/100/database/com.example.menurecipe/rdb/MenuRecipe.db

特点:

  • 应用私有目录,其他应用无法访问
  • 应用卸载时会被清除
  • 应用更新时数据保留

四、验证测试

4.1 测试步骤

第一次测试:

  1. 启动应用
  2. 添加菜谱"凉拌猪耳朵"
  3. 查看菜谱列表,确认菜谱在
    在这里插入图片描述
    第二次测试:
  4. 完全关闭应用(从后台清除)
  5. 重新打开应用
  6. 查看菜谱列表
    在这里插入图片描述

4.2 测试结果

修复前:

  • ❌ 重启后菜谱列表为空
  • ❌ 数据库文件被删除重建

修复后:

  • ✅ 重启后菜谱列表正常显示
  • ✅ 3个菜谱都在列表中
  • ✅ 图片路径正确保存
  • ✅ 数据库文件保留

4.3 日志验证

查看应用日志:

[INFO] RdbUtil: 开始初始化数据库
[INFO] RdbUtil: 数据库初始化完成

说明:

  • 没有出现"已删除旧数据库"的日志
  • 数据库直接打开,没有重建

五、最佳实践

5.1 数据库初始化建议

开发阶段:

// 可以使用环境变量控制
if (BuildConfig.DEBUG) {
  // 仅在调试模式删除数据库
  try {
    await relationalStore.deleteRdbStore(context, DB_NAME)
    LogUtil.info(TAG, 'DEBUG模式:删除旧数据库')
  } catch (err) {
    // 忽略错误
  }
}

发布阶段:

  • 必须移除删除数据库的逻辑
  • 确保数据能够持久化
  • 考虑数据库版本管理

5.2 数据库版本管理

如果需要修改表结构,应该使用版本管理:

// 检查数据库版本
const version = await this.getVersion()

if (version < 2) {
  // 升级到版本2
  await this.upgradeToV2()
}

if (version < 3) {
  // 升级到版本3
  await this.upgradeToV3()
}

优点:

  • 保留用户数据
  • 平滑升级
  • 避免数据丢失

六、总结

本篇文章解决了数据持久化问题:

问题原因:

  • 开发阶段的删除数据库代码没有移除
  • 每次启动都会重建数据库

解决方案:

  • 移除 deleteRdbStore 调用
  • 使用 getRdbStore 自动创建或打开数据库

修复效果:

  • ✅ 菜谱数据能够持久保存
  • ✅ 重启后数据不丢失
  • ✅ 应用真正具备了实用价值

这个问题提醒我们:开发阶段的临时代码,一定要在发布前仔细检查和清理,否则可能带来严重的后果。


Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐