在 HarmonyOS 开发中,当应用需要存储结构化、关系复杂的数据(如订单、联系人、消息记录等)时,轻量级的 Preferences 或 KVDB 往往无法满足需求。此时,RelationalStore(关系型数据库) 是最佳选择。它底层基于 SQLite 引擎,提供了一套完整的本地数据库管理机制。

以下是基于最新 API (@kit.ArkData) 的 RelationalStore 完整操作指南:

一、 核心概念与适用场景

  • 数据结构:采用关系型表结构,支持完整的 SQL 语法(包括事务、索引、视图、触发器等)。
  • 适用场景:存储包含复杂关系的数据,例如包含姓名、学号、各科成绩的学生信息,或公司的雇员信息。
  • 数据限制:为保证插入并读取成功,建议单条数据大小不要超过 2M。

二、 核心 API 与基础操作

1. 导入模块与初始化

推荐使用新版 @kit.ArkData 模块(旧版 @ohos.data.rdb 已停止维护)。

import { relationalStore } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';

// 1. 定义数据库配置
const STORE_CONFIG: relationalStore.StoreConfig = {
  name: 'my_database.db', // 数据库文件名
  securityLevel: relationalStore.SecurityLevel.S1 // 安全级别
};

// 2. 获取 RdbStore 实例(通常在 Ability 或全局工具类中执行)
let rdbStore: relationalStore.RdbStore | undefined = undefined;
rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
2. 创建数据表

通过 executeSql 执行标准的 SQL 建表语句:

const CREATE_TABLE_SQL = 'CREATE TABLE IF NOT EXISTS EMPLOYEE (' +
  'employeeId TEXT PRIMARY KEY, ' +
  'name TEXT NOT NULL, ' +
  'age INTEGER, ' +
  'salary REAL NOT NULL)';
await rdbStore.executeSql(CREATE_TABLE_SQL);
3. 增删改查 (CRUD) 实战
  • 增加 (Insert):使用 ValuesBucket 传递键值对数据,成功返回行 ID。
const valueBucket: relationalStore.ValuesBucket = {
  'employeeId': 'E001',
  'name': '张三',
  'age': 28,
  'salary': 15000.0
};
const rowId = await rdbStore.insert('EMPLOYEE', valueBucket);
  • 删除 (Delete):使用 RdbPredicates 定义删除条件。
const predicates = new relationalStore.RdbPredicates('EMPLOYEE');
predicates.equalTo('employeeId', 'E001'); // 指定删除条件
const deletedRows = await rdbStore.delete(predicates);
  • 修改 (Update):结合 ValuesBucket 和 RdbPredicates
const valueBucket: relationalStore.ValuesBucket = { 'salary': 18000.0 };
const predicates = new relationalStore.RdbPredicates('EMPLOYEE');
predicates.equalTo('employeeId', 'E001');
const updatedRows = await rdbStore.update(valueBucket, predicates);
  • 查询 (Query):返回 ResultSet 结果集,需手动遍历并务必关闭
const predicates = new relationalStore.RdbPredicates('EMPLOYEE');
const resultSet = await rdbStore.query(predicates, ['name', 'salary']);
while (resultSet.goToNextRow()) {
  const name = resultSet.getString(resultSet.getColumnIndex('name'));
  const salary = resultSet.getDouble(resultSet.getColumnIndex('salary'));
  console.info(`员工: ${name}, 薪资: ${salary}`);
}
resultSet.close(); // 【关键】使用完毕后必须关闭结果集

三、 进阶能力:分布式与端云同步

RelationalStore 的一大亮点是支持跨设备/端云的数据同步。

  1. 设置分布式同步表:通过 setDistributedTables 将指定的表标记为支持分布式同步。
  2. 同步策略:支持自动同步 (autoSync: true) 和手动同步 (cloudSync)。手动同步可配置 SYNC_MODE_TIME_FIRST 等模式,决定数据流向。
  3. 数据变化订阅:通过 on("dataChange") 监听云端或其他设备的数据变更,结合 cursor 机制精准拉取增量数据。

四、 开发约束与避坑指南

  1. 并发写入限制:为保证数据准确性,数据库同一时间只能支持一个写操作(系统默认有 4 个读连接和 1 个写连接)。
  2. 线程限制:RelationalStore 不支持在 Worker 线程中直接使用,必须在主线程或 TaskPool 中通过特定方式调用。
  3. 事务处理:对于批量插入或高并发写入场景,强烈建议使用事务 (Transaction) 包裹操作。实测表明,使用事务的性能比非事务高出约 200 倍。
  4. 生命周期清理:当应用被卸载后,设备上的相关数据库文件及临时文件会被系统自动清除。

五、 深度扩展

在掌握了 RelationalStore 的基础 CRUD 操作后,为了应对真实商业项目的复杂需求,我们需要在性能优化、架构设计、高级特性三个维度进行深度扩展。以下是鸿蒙关系型数据库的进阶实战指南:

1、 性能优化:事务与批量操作

在需要大量写入数据的场景(如首次安装应用拉取离线数据、导入导出报表)中,逐条插入会导致严重的性能瓶颈。

1.1、 批量插入 (batchInsert)
使用 batchInsert 接口可以一次性插入多条数据,大幅减少系统调用开销。

let valuesList: relationalStore.ValuesBucket[] = [];
for (let i = 0; i < 1000; i++) {
  valuesList.push({ 'name': `User_${i}`, 'age': 20 + (i % 10) });
}
// 返回实际成功插入的行数
let count = await rdbStore.batchInsert('EMPLOYEE', valuesList); 

1.2、 事务管理 (Transaction)
对于涉及多表更新或必须保证原子性的操作,应使用事务。事务能确保操作要么全部成功,要么全部回滚,避免产生脏数据。

let transaction = await rdbStore.createTransaction({});
try {
  await transaction.execute(`INSERT INTO EMPLOYEE (name, age) VALUES ('Alice', 25)`);
  await transaction.execute(`UPDATE EMPLOYEE SET age = 26 WHERE name = 'Bob'`);
  await transaction.commit(); // 提交事务
} catch (err) {
  await transaction.rollback(); // 发生异常时回滚
}
2、 架构设计:通用数据库管理类封装

为了避免在业务代码中散落大量的数据库操作逻辑,建议封装一个通用的 RdbManager 工具类,统一管理数据库的初始化、版本升级和 CRUD 操作。

核心设计思路:

  1. 单例模式:确保全局只有一个数据库连接实例。
  2. 版本控制:通过 PRAGMA user_version 追踪数据库版本,在 onUpgrade 回调中执行表结构的平滑升级(如新增字段、新建表)。
  3. 统一异常处理:封装内部 try-catch,对外暴露清晰的 Promise 接口。
// 简化的通用管理类示例
export class RdbManager {
  private rdbStore: relationalStore.RdbStore | undefined = undefined;

  async initDatabase(context: common.UIAbilityContext) {
    const config: relationalStore.StoreConfig = { name: 'app.db', securityLevel: relationalStore.SecurityLevel.S1 };
    this.rdbStore = await relationalStore.getRdbStore(context, config);
    // 在此处执行建表或版本升级逻辑
  }

  async insert(table: string, values: relationalStore.ValuesBucket): Promise<number> {
    if (!this.rdbStore) throw new Error('DB not initialized');
    return await this.rdbStore.insert(table, values);
  }
}
3、 高级特性:全文检索 (FTS)

对于聊天消息、文章列表等需要关键字搜索的场景,传统的 LIKE '%keyword%' 查询效率极低。RelationalStore 内置了 FTS (Full-Text Search) 引擎,支持中文 ICU 分词器。

3.1、 创建全文检索虚拟表

const SQL_CREATE_TABLE = 'CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts4(title, content, tokenize=icu zh_CN)';
await rdbStore.executeSql(SQL_CREATE_TABLE);

3.2、 执行全文检索
使用 MATCH 语法进行高效查询:

let predicates = new relationalStore.RdbPredicates('articles');
predicates.match('content', '鸿蒙开发'); // 搜索包含“鸿蒙开发”的文章
let resultSet = await rdbStore.query(predicates, ['title', 'content']);
4、 分布式与端云数据同步机制

RelationalStore 提供了强大的分布式能力,支持设备间、端云间的数据无缝流转。

4.1、 设置分布式表
通过 setDistributedTables 将需要同步的表标记为分布式表,并配置 autoSync: true 开启自动同步。

let config: relationalStore.DistributedConfig = { autoSync: true };
rdbStore.setDistributedTables(['EMPLOYEE'], relationalStore.DistributedType.DISTRIBUTED_CLOUD, config);

4.2、 增量数据感知 (Cursor 机制)
在端云同步场景中,如何知道哪些数据是最新变化的?系统为每行数据绑定了 cursor 字段。每次增删改操作,该字段都会递增。

  • 应用只需记录上次的最大 cursor 值。
  • 使用 predicates.greaterThan(relationalStore.Field.CURSOR_FIELD, lastCursor) 即可精准拉取增量数据。

4.3、 订阅数据变化
通过 on("dataChange") 监听云端或其他组网设备的数据变更,一旦收到通知,立即触发增量拉取并刷新本地 UI。

5、 进阶避坑与约束
  1. 动态库加载限制:如果使用了自定义分词器扩展(如通过 pluginLibs 加载 .so 文件),需注意动态库数量最多为 16个,且必须包含全部依赖,否则会导致开库失败(错误码 14800000/14800010)。
  2. 脏数据处理:在端云同步中,如果开库时将 autoCleanDirtyData 设为 false,云端删除数据时不会自动删除本地数据。此时必须通过 cursor 查出被标记删除的数据,并手动调用 cleanDirtyData 方法进行清理。
  3. Returning 子句约束:在执行带有 returning 关键字的 SQL 操作时,指定返回的字段名不能包含空格、逗号及星号,且最多支持返回 1 到 4 个字段。
Logo

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

更多推荐