【HarmonyOS Relational Database】鸿蒙关系型数据库

基本介绍

在鸿蒙系统中,relationalStore 是 ArkTS 提供的关系型数据库模块,用于管理本地结构化数据。它支持 SQL 查询、事务处理、条件查询等常见数据库操作,适用于需要持久化存储结构化数据的场景。

  • 包路径:@kit.ArkData
  • 核心类:
    • relationalStore.getRdbStore():获取或创建一个数据库实例
    • relationalStore.RdbStore:表示一个具体的数据库对象
    • relationalStore.RdbPredicates:构建查询/更新/删除条件语句
    • relationalStore.ResultSet:封装查询结果集

代码实现

typescript 复制代码
import { relationalStore } from '@kit.ArkData'
import { CONTEXT } from '../constants'

// 录音数据类型
export interface InterviewAudioItem extends relationalStore.ValuesBucket {
  id: number | null
  user_id: string
  name: string
  path: string
  duration: number
  size: number
  create_time: number
}

class AudioDB {
  store?: relationalStore.RdbStore
  tableName: string = 'interview_audio'

  /**
   * 初始化数据库和建表
   */
  async initStore() {
    const ctx = AppStorage.get<Context>(CONTEXT)
    if (ctx) {
      const store = await relationalStore.getRdbStore(ctx, {
        name: 'interview_tong.db',
        securityLevel: relationalStore.SecurityLevel.S1
      })
      const sql = `
        CREATE TABLE IF NOT EXISTS ${this.tableName} (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          user_id TEXT NOT NULL,
          name TEXT NOT NULL,
          path TEXT NOT NULL,
          duration INTEGER NOT NULL,
          size INTEGER NOT NULL,
          create_time INTEGER NOT NULL
        )
      `
      await store.executeSql(sql)
      // 记录数据库实例
      this.store = store
    }
  }

  /**
   * 添加
   * @param interviewAudioItem 录音信息对象
   * @returns Promise<void>
   */
  async insert(interviewAudioItem: InterviewAudioItem) {
    // rowId 是插入成功的行ID,-1 代表失败
    const rowId = await this.store?.insert(this.tableName, interviewAudioItem)
    if (rowId === undefined || rowId === -1) {
      return Promise.reject('insert fail')
    } else {
      return Promise.resolve()
    }
  }

  /**
   * 删除
   * @param id 录音数据的ID
   * @returns Promise<void>
   */
  async delete(id: number) {
    const predicates = new relationalStore.RdbPredicates(this.tableName)
    predicates.equalTo('id', id)
    // rowCount 是删除影响的行数,删除了多少条
    const rowCount = await this.store?.delete(predicates)
    if (rowCount === undefined || rowCount <= 0) {
      return Promise.reject('delete fail')
    } else {
      return Promise.resolve()
    }
  }

  /**
   * 修改
   * @param interviewAudioItem 录音信息对象
   * @returns Promise<void>
   */
  async update(interviewAudioItem: InterviewAudioItem) {
    const predicates = new relationalStore.RdbPredicates(this.tableName)
    predicates.equalTo('id', interviewAudioItem.id)
    // rowCount 是修改影响的行数
    const rowCount = await this.store?.update(interviewAudioItem, predicates)
    if (rowCount === undefined || rowCount <= 0) {
      return Promise.reject('update fail')
    } else {
      return Promise.resolve()
    }
  }

  /**
   * 查询用户的录音
   * @param userId
   * @returns Promise<InterviewAudioItem[]>
   */
  async query(userId: string) {
    const predicates = new relationalStore.RdbPredicates(this.tableName)
    // 查询当前用户下的录音信息
    predicates.equalTo('user_id', userId)
    const resultSet = await this.store?.query(predicates)
    // 没有结果查询失败
    if (!resultSet) {
      return Promise.reject('query fail')
    }
    const list: InterviewAudioItem[] = []
    while (resultSet.goToNextRow()) {
      list.push({
        id: resultSet.getLong(resultSet.getColumnIndex('id')),
        user_id: resultSet.getString(resultSet.getColumnIndex('user_id')),
        name: resultSet.getString(resultSet.getColumnIndex('name')),
        path: resultSet.getString(resultSet.getColumnIndex('path')),
        duration: resultSet.getLong(resultSet.getColumnIndex('duration')),
        size: resultSet.getLong(resultSet.getColumnIndex('size')),
        create_time: resultSet.getLong(resultSet.getColumnIndex('create_time'))
      })
    }
    resultSet.close()
    return Promise.resolve(list)
  }
}


export const audioDB = new AudioDB()

结构说明

1. 数据表定义与初始化

表名

ts 复制代码
tableName: string = 'interview_audio'

字段定义(见 InterviewAudioItem 接口)

字段名 类型 约束 描述
id INTEGER PRIMARY KEY AUTOINCREMENT 主键,自增
user_id TEXT NOT NULL 用户ID
name TEXT NOT NULL 录音名称
path TEXT NOT NULL 文件路径
duration INTEGER NOT NULL 时长(毫秒)
size INTEGER NOT NULL 文件大小(字节)
create_time INTEGER NOT NULL 创建时间戳(毫秒)

初始化数据库与建表

ts 复制代码
async initStore()
  • 使用 relationalStore.getRdbStore() 获取或创建数据库文件 interview_tong.db
  • 设置安全等级为 S1
  • 执行建表 SQL 语句(若表不存在)
  • 将数据库实例保存到 this.store 中供后续使用

2. 数据库操作方法详解

✅ 插入数据:insert(interviewAudioItem: InterviewAudioItem)

  • 使用 store.insert(table, values) 方法插入一条记录
  • 返回值:
    • 成功:Promise.resolve()
    • 失败:Promise.reject('insert fail')
  • 注意事项:
    • interviewAudioItem 必须符合 ValuesBucket 结构(键值对形式)

❌ 删除数据:delete(id: number)

  • 构造 RdbPredicates 条件:id = ?
  • 调用 store.delete(predicates) 删除符合条件的数据
  • 返回值:
    • 成功:Promise.resolve()
    • 失败:Promise.reject('delete fail')

🔁 更新数据:update(interviewAudioItem: InterviewAudioItem)

  • 构造 RdbPredicates 条件:id = interviewAudioItem.id
  • 调用 store.update(values, predicates) 更新指定字段
  • 返回值:
    • 成功:Promise.resolve()
    • 失败:Promise.reject('update fail')

🔍 查询数据:query(userId: string)

  • 构造 RdbPredicates 条件:user_id = userId
  • 调用 store.query(predicates) 查询数据,返回 ResultSet
  • 遍历 ResultSet 并将每条记录转换为 InterviewAudioItem 对象
  • 最终返回 Promise<InterviewAudioItem[]>
  • 注意事项:
    • 使用完 ResultSet 后必须调用 .close() 关闭资源

使用建议与注意事项

✅ 建议

  • 所有数据库操作应放在异步函数中执行(已实现)
  • 使用 RdbPredicates 可以避免手动拼接 SQL 语句,提高安全性
  • query() 中关闭 ResultSet 是良好习惯,防止内存泄漏

⚠️ 注意

  • store 可能为 undefined,因此每次操作都应加可选链判断(如 this.store?.insert(...)
  • AppStorage.get<Context>(CONTEXT) 必须正确配置上下文环境
  • 表名、字段名尽量统一命名规范,避免 SQL 注入风险

总结

AudioDB 类是一个完整的数据库访问层(DAO),封装了录音数据的 CRUD 操作,并通过 ArkTS 的 relationalStore 模块实现了鸿蒙平台上的本地持久化能力。整体结构清晰,逻辑合理,适合用于 HarmonyOS 应用中的录音信息管理模块。

相关推荐
Georgewu8 小时前
【 HarmonyOS 5 入门系列 】鸿蒙HarmonyOS示例项目讲解
harmonyos
libo_202510 小时前
HarmonyOS5 元宇宙3D原子化服务开发实践
harmonyos
半路下车10 小时前
【Harmony OS 5】DevEco Testing重塑教育质量
harmonyos·arkts
90后的晨仔10 小时前
解析鸿蒙 ArkTS 中的 Union 类型与 TypeAliases类型
前端·harmonyos
风浅月明10 小时前
[Harmony]颜色初始化
harmonyos·color
风浅月明11 小时前
[Harmony]网络状态监听
harmonyos·网络状态
半路下车11 小时前
【Harmony OS 5】DevEco Testing在教育领域的应用与实践
harmonyos·产品
哼唧唧_12 小时前
使用 React Native 开发鸿蒙(HarmonyOS)运动健康类应用的系统化准备工作
react native·react.js·harmonyos·harmony os5·运动健康
三掌柜66612 小时前
HarmonyOS开发:显示图片功能详解
华为·harmonyos