news 2026/4/15 18:17:57

[鸿蒙2025领航者闯关]使用RelationalStore实现增删改查(CRUD)操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[鸿蒙2025领航者闯关]使用RelationalStore实现增删改查(CRUD)操作

问题描述

在 HarmonyOS 应用开发中,如何使用 RelationalStore 实现数据库的增删改查(CRUD)操作?很多开发者在使用关系型数据库时遇到以下问题:

  • 不清楚如何正确初始化数据库
  • 不知道如何设计 Dao 层
  • 查询结果集如何转换为对象
  • 如何处理异步操作

解决方案

1. 技术原理

RelationalStore 是 HarmonyOS 提供的关系型数据库解决方案,基于 SQLite 实现。核心流程:

DatabaseHelper(单例) → 初始化RdbStore → 创建表结构 → Dao层操作

2. 完整实现代码

步骤 1: 创建数据库管理类
import relationalStore from '@ohos.data.relationalStore'; ​ export class DatabaseHelper { private static instance: DatabaseHelper; private rdbStore: relationalStore.RdbStore | null = null; private readonly DB_NAME: string = 'app_database.db'; private readonly DB_VERSION: number = 1; private constructor() {} /** * 获取单例 */ static getInstance(): DatabaseHelper { if (!DatabaseHelper.instance) { DatabaseHelper.instance = new DatabaseHelper(); } return DatabaseHelper.instance; } /** * 初始化数据库 */ async init(context: Context): Promise<void> { const config: relationalStore.StoreConfig = { name: this.DB_NAME, securityLevel: relationalStore.SecurityLevel.S1 }; this.rdbStore = await relationalStore.getRdbStore(context, config); await this.createTables(); } /** * 创建表结构 */ private async createTables(): Promise<void> { const createTableSql = ` CREATE TABLE IF NOT EXISTS user ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, nickname TEXT, email TEXT, create_time INTEGER, update_time INTEGER ) `; await this.rdbStore!.executeSql(createTableSql); } /** * 获取数据库实例 */ getStore(): relationalStore.RdbStore { if (!this.rdbStore) { throw new Error('Database not initialized'); } return this.rdbStore; } }
步骤 2: 创建数据模型
export class User { id: number = 0; username: string = ''; nickname: string = ''; email: string = ''; createTime: number = 0; updateTime: number = 0; /** * 从数据库记录创建对象 */ static fromDb(record: Record<string, Object>): User { const user = new User(); user.id = record['id'] as number; user.username = record['username'] as string; user.nickname = record['nickname'] as string; user.email = record['email'] as string; user.createTime = record['create_time'] as number; user.updateTime = record['update_time'] as number; return user; } }
步骤 3: 实现 Dao 层
import relationalStore from '@ohos.data.relationalStore'; import { User } from '../models/User'; import { DatabaseHelper } from './DatabaseHelper'; ​ const TABLE_NAME = 'user'; ​ export class UserDao { private dbHelper: DatabaseHelper; constructor() { this.dbHelper = DatabaseHelper.getInstance(); } /** * 插入用户 */ async insert(user: User): Promise<number> { const store = this.dbHelper.getStore(); const valueBucket: relationalStore.ValuesBucket = { username: user.username, nickname: user.nickname, email: user.email, create_time: Date.now(), update_time: Date.now() }; return await store.insert(TABLE_NAME, valueBucket); } /** * 更新用户 */ async update(user: User): Promise<number> { const store = this.dbHelper.getStore(); const valueBucket: relationalStore.ValuesBucket = { nickname: user.nickname, email: user.email, update_time: Date.now() }; const predicates = new relationalStore.RdbPredicates(TABLE_NAME); predicates.equalTo('id', user.id); return await store.update(valueBucket, predicates); } /** * 根据ID查询 */ async findById(id: number): Promise<User | null> { const store = this.dbHelper.getStore(); const predicates = new relationalStore.RdbPredicates(TABLE_NAME); predicates.equalTo('id', id); const resultSet = await store.query(predicates); let user: User | null = null; if (resultSet.goToFirstRow()) { const record = this.resultSetToRecord(resultSet); user = User.fromDb(record); } resultSet.close(); return user; } /** * 查询所有用户 */ async findAll(): Promise<User[]> { const store = this.dbHelper.getStore(); const predicates = new relationalStore.RdbPredicates(TABLE_NAME); const resultSet = await store.query(predicates); const users: User[] = []; while (resultSet.goToNextRow()) { const record = this.resultSetToRecord(resultSet); users.push(User.fromDb(record)); } resultSet.close(); return users; } /** * 删除用户 */ async delete(id: number): Promise<number> { const store = this.dbHelper.getStore(); const predicates = new relationalStore.RdbPredicates(TABLE_NAME); predicates.equalTo('id', id); return await store.delete(predicates); } /** * 将ResultSet转换为记录对象 */ private resultSetToRecord(resultSet: relationalStore.ResultSet): Record<string, Object> { const record: Record<string, Object> = {}; const columnNames = resultSet.columnNames; for (const name of columnNames) { const index = resultSet.getColumnIndex(name); const type = resultSet.getColumnType(index); switch (type) { case relationalStore.ColumnType.TYPE_INTEGER: record[name] = resultSet.getLong(index); break; case relationalStore.ColumnType.TYPE_STRING: record[name] = resultSet.getString(index); break; case relationalStore.ColumnType.TYPE_FLOAT: record[name] = resultSet.getDouble(index); break; default: record[name] = resultSet.getString(index); } } return record; } }
步骤 4: 在 EntryAbility 中初始化
import { DatabaseHelper } from '../database/DatabaseHelper'; ​ export default class EntryAbility extends UIAbility { async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> { // 初始化数据库 await DatabaseHelper.getInstance().init(this.context); } }
步骤 5: 使用示例
import { UserDao } from '../database/UserDao'; import { User } from '../models/User'; ​ // 创建用户 const userDao = new UserDao(); const user = new User(); user.username = 'zhangsan'; user.nickname = '张三'; user.email = 'zhangsan@example.com'; ​ const userId = await userDao.insert(user); console.log('插入用户ID:', userId); ​ // 查询用户 const foundUser = await userDao.findById(userId); console.log('查询到用户:', foundUser?.nickname); ​ // 更新用户 if (foundUser) { foundUser.nickname = '张三三'; await userDao.update(foundUser); } ​ // 查询所有用户 const allUsers = await userDao.findAll(); console.log('用户总数:', allUsers.length); ​ // 删除用户 await userDao.delete(userId);

3. 运行效果

[日志] 插入用户ID: 1 [日志] 查询到用户: 张三 [日志] 用户总数: 1 [日志] 删除成功

关键要点

1. 单例模式

DatabaseHelper 使用单例模式,确保全局只有一个数据库实例,避免资源浪费。

2. 异步操作

所有数据库操作都是异步的,使用async/await确保数据一致性。

3. ResultSet 处理

  • 必须调用goToFirstRow()goToNextRow()移动游标
  • 使用完毕后必须调用close()释放资源
  • 根据列类型使用对应的 getter 方法

4. ValuesBucket

插入和更新操作使用ValuesBucket传递数据,字段名必须与表结构一致。

5. RdbPredicates

查询和删除操作使用RdbPredicates构建条件,支持链式调用:

predicates .equalTo('status', 1) .and() .greaterThan('age', 18) .orderByAsc('create_time');

常见问题

Q1: 如何处理数据库初始化失败?

async init(context: Context): Promise<void> { try { const config: relationalStore.StoreConfig = { name: this.DB_NAME, securityLevel: relationalStore.SecurityLevel.S1 }; this.rdbStore = await relationalStore.getRdbStore(context, config); await this.createTables(); } catch (err) { console.error('数据库初始化失败:', JSON.stringify(err)); throw err; } }

Q2: 如何实现分页查询?

async findByPage(page: number, pageSize: number): Promise<User[]> { const store = this.dbHelper.getStore(); const predicates = new relationalStore.RdbPredicates(TABLE_NAME); predicates.limitAs(pageSize).offsetAs((page - 1) * pageSize); const resultSet = await store.query(predicates); const users: User[] = []; while (resultSet.goToNextRow()) { const record = this.resultSetToRecord(resultSet); users.push(User.fromDb(record)); } resultSet.close(); return users; }

Q3: 如何执行复杂 SQL 查询?

async customQuery(sql: string, args: Array<string | number>): Promise<any[]> { const store = this.dbHelper.getStore(); const resultSet = await store.querySql(sql, args); const results: any[] = []; while (resultSet.goToNextRow()) { results.push(this.resultSetToRecord(resultSet)); } resultSet.close(); return results; }

总结

本文展示了 HarmonyOS 中 RelationalStore 的完整 CRUD 实现方案:

  • ✅ 单例模式管理数据库实例
  • ✅ 规范的 Dao 层设计
  • ✅ 类型安全的数据转换
  • ✅ 完善的错误处理
  • ✅ 支持复杂查询

参考资料

  • HarmonyOS 关系型数据库开发指南
  • RelationalStore API 文档
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!