《静默登录》一、通过关系型数据库实现数据持久化使用指南
鸿蒙智多星
·
通过关系型数据库实现数据持久化 (ArkTS) 使用指南
效果
一、概述
HarmonyOS 提供了基于 SQLite 的关系型数据库(RelationalStore),适用于存储结构化、具有复杂关系的数据。开发者可以通过 @kit.ArkData 中的 relationalStore 模块,对本地数据进行增删改查操作,实现数据的持久化存储。
1.1 适用场景
- 用户账号信息的本地缓存
- 订单、商品等结构化数据存储
- 离线数据的本地保存与同步
- 聊天记录、笔记等频繁增删改查的数据
1.2 核心概念
| 概念 | 说明 |
|---|---|
| RdbStore | 关系型数据库实例,通过 getRdbStore 获取,是操作数据库的入口 |
| StoreConfig | 数据库配置对象,包含数据库文件名、安全等级、是否加密等 |
| ValuesBucket | 数据容器,以键值对形式存储一行数据,键为字段名,值为字段值 |
| RdbPredicates | 查询谓词,用于构建 WHERE 条件,支持链式调用 |
| ResultSet | 查询结果集(游标),需手动遍历并在使用后关闭 |
二、环境准备
2.1 导入模块
import { relationalStore } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
2.2 数据库安全等级说明
| 等级 | 说明 |
|---|---|
| S1 | 最低安全等级,适用于非敏感数据 |
| S2 | 中等安全等级 |
| S3 | 较高安全等级,适用于一般敏感数据 |
| S4 | 最高安全等级,适用于高度敏感数据(如用户隐私) |
三、实现流程
3.1 第一步:获取数据库实例(建库)
通过 relationalStore.getRdbStore 方法获取 RdbStore 实例:
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'myApp.db', // 数据库文件名
securityLevel: relationalStore.SecurityLevel.S1 // 安全等级
};
let rdbStore: relationalStore.RdbStore | undefined = undefined;
async function initDatabase(context: Context): Promise<void> {
try {
rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
hilog.info(0x0000, 'RDB', 'Succeeded in getting RdbStore.');
} catch (err) {
hilog.error(0x0000, 'RDB', 'Failed to get RdbStore: %{public}s', JSON.stringify(err));
}
}
注意:
RdbStore是单例的,同一个数据库文件在应用中只需创建一次,其他地方直接复用即可。
3.2 第二步:创建数据表(建表)
使用 executeSql 执行 SQL 语句创建表结构:
const CREATE_TABLE_SQL = `CREATE TABLE IF NOT EXISTS userInfo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
userName TEXT NOT NULL,
email TEXT NOT NULL,
age INTEGER,
createTime TEXT
)`;
async function createTable(): Promise<void> {
if (rdbStore) {
await rdbStore.executeSql(CREATE_TABLE_SQL);
hilog.info(0x0000, 'RDB', 'Succeeded in creating table.');
}
}
关键点:务必使用
IF NOT EXISTS,避免应用第二次启动时因表已存在而报错。
3.3 第三步:插入数据(增)
使用 ValuesBucket 封装数据,调用 insert 方法插入:
async function insertUser(userName: string, email: string, age: number): Promise<number> {
const valueBucket: relationalStore.ValuesBucket = {
userName: userName,
email: email,
age: age,
createTime: new Date().toISOString()
};
if (rdbStore) {
const rowId = await rdbStore.insert('userInfo', valueBucket);
hilog.info(0x0000, 'RDB', 'Succeeded in inserting, rowId: %{public}d', rowId);
return rowId;
}
return -1;
}
ValuesBucket本质是键值对对象,键对应表的字段名,值对应字段值。插入后自增id会自动生成。
3.4 第四步:查询数据(查)
使用 RdbPredicates 构建查询条件,调用 query 方法获取 ResultSet:
interface UserInfo {
id: number;
userName: string;
email: string;
age: number;
}
async function queryAllUsers(): Promise<UserInfo[]> {
const predicates = new relationalStore.RdbPredicates('userInfo');
predicates.orderByDesc('createTime'); // 按创建时间倒序
const resultList: UserInfo[] = [];
if (rdbStore) {
const resultSet = await rdbStore.query(predicates, ['id', 'userName', 'email', 'age']);
while (resultSet.goToNextRow()) {
const user: UserInfo = {
id: resultSet.getLong(resultSet.getColumnIndex('id')),
userName: resultSet.getString(resultSet.getColumnIndex('userName')),
email: resultSet.getString(resultSet.getColumnIndex('email')),
age: resultSet.getLong(resultSet.getColumnIndex('age'))
};
resultList.push(user);
}
resultSet.close(); // 【重要】使用完毕后必须关闭结果集
}
return resultList;
}
重要:
ResultSet是游标对象,使用完毕后必须调用close()方法释放资源,否则会造成内存泄漏。
3.5 第五步:更新数据(改)
结合 ValuesBucket 和 RdbPredicates 实现条件更新:
async function updateUserName(id: number, newUserName: string): Promise<number> {
const valueBucket: relationalStore.ValuesBucket = {
userName: newUserName
};
const predicates = new relationalStore.RdbPredicates('userInfo');
predicates.equalTo('id', id);
if (rdbStore) {
const updatedRows = await rdbStore.update(valueBucket, predicates);
hilog.info(0x0000, 'RDB', 'Updated %{public}d rows', updatedRows);
return updatedRows;
}
return 0;
}
更新时只需在
ValuesBucket中放入要修改的字段,未指定的字段保持不变。
3.6 第六步:删除数据(删)
使用 RdbPredicates 指定删除条件:
async function deleteUser(id: number): Promise<number> {
const predicates = new relationalStore.RdbPredicates('userInfo');
predicates.equalTo('id', id);
if (rdbStore) {
const deletedRows = await rdbStore.delete(predicates);
hilog.info(0x0000, 'RDB', 'Deleted %{public}d rows', deletedRows);
return deletedRows;
}
return 0;
}
四、完整示例:待办事项管理器
以下是一个完整的待办事项 CRUD 示例,涵盖建库、建表、增删改查全流程。
4.1 定义数据模型
// TodoItem.ets
export interface TodoItem {
id: number;
title: string;
done: boolean;
createTime: string;
}
4.2 封装数据库管理类
// TodoDatabase.ets
import { relationalStore } from '@kit.ArkData';
import { TodoItem } from './TodoItem';
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'todo.db',
securityLevel: relationalStore.SecurityLevel.S1
};
const CREATE_TABLE_SQL = `CREATE TABLE IF NOT EXISTS todo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
done INTEGER DEFAULT 0,
createTime TEXT
)`;
export class TodoDatabase {
private rdbStore: relationalStore.RdbStore | null = null;
async init(context: Context): Promise<void> {
this.rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
await this.rdbStore.executeSql(CREATE_TABLE_SQL);
}
async addTodo(title: string): Promise<number> {
const value: relationalStore.ValuesBucket = {
title: title,
done: 0,
createTime: new Date().toISOString()
};
return await this.rdbStore!.insert('todo', value);
}
async getAllTodos(): Promise<TodoItem[]> {
const predicates = new relationalStore.RdbPredicates('todo');
predicates.orderByDesc('createTime');
const resultSet = await this.rdbStore!.query(predicates, ['id', 'title', 'done']);
const list: TodoItem[] = [];
while (resultSet.goToNextRow()) {
list.push({
id: resultSet.getLong(resultSet.getColumnIndex('id')),
title: resultSet.getString(resultSet.getColumnIndex('title')),
done: resultSet.getLong(resultSet.getColumnIndex('done')) === 1,
createTime: resultSet.getString(resultSet.getColumnIndex('createTime'))
});
}
resultSet.close();
return list;
}
async toggleTodo(id: number, done: boolean): Promise<number> {
const value: relationalStore.ValuesBucket = { done: done ? 1 : 0 };
const predicates = new relationalStore.RdbPredicates('todo');
predicates.equalTo('id', id);
return await this.rdbStore!.update(value, predicates);
}
async deleteTodo(id: number): Promise<number> {
const predicates = new relationalStore.RdbPredicates('todo');
predicates.equalTo('id', id);
return await this.rdbStore!.delete(predicates);
}
}
4.3 页面中使用
// TodoPage.ets
import { TodoDatabase } from '../database/TodoDatabase';
import { TodoItem } from '../database/TodoItem';
@Entry
@Component
struct TodoPage {
@State todoList: TodoItem[] = [];
@State inputText: string = '';
private db: TodoDatabase = new TodoDatabase();
async aboutToAppear() {
await this.db.init(getContext(this));
this.todoList = await this.db.getAllTodos();
}
build() {
Column() {
// 输入区域
Row() {
TextInput({ placeholder: '输入待办事项' })
.onChange((value: string) => { this.inputText = value; })
.layoutWeight(1)
Button('添加')
.onClick(async () => {
if (this.inputText.trim() !== '') {
await this.db.addTodo(this.inputText);
this.todoList = await this.db.getAllTodos();
this.inputText = '';
}
})
}
.width('90%')
.margin({ top: 20 })
// 列表展示
List() {
ForEach(this.todoList, (item: TodoItem) => {
ListItem() {
Row() {
Text(item.title)
.fontSize(16)
.decoration({ type: item.done ? TextDecorationType.LineThrough : TextDecorationType.None })
.layoutWeight(1)
Button(item.done ? '撤销' : '完成')
.onClick(async () => {
await this.db.toggleTodo(item.id, !item.done);
this.todoList = await this.db.getAllTodos();
})
Button('删除')
.onClick(async () => {
await this.db.deleteTodo(item.id);
this.todoList = await this.db.getAllTodos();
})
}
.width('100%')
.padding(10)
}
})
}
.width('90%')
.margin({ top: 20 })
}
.width('100%')
.height('100%')
}
}
五、常见误区与注意事项
| 误区 | 说明 |
|---|---|
建表漏掉 IF NOT EXISTS |
应用第二次启动时表已存在,再次 CREATE TABLE 会报错 |
ResultSet 不 close() |
查询返回的游标占用资源,用完必须关闭,否则内存泄漏 |
| 忘记主键自增 | 未设 AUTOINCREMENT,手动插入相同 id 会冲突 |
| 一条数据超过 2MB | 超过 2MB 的数据可能插入成功但读取失败 |
| 数据库安全等级过低 | 涉及用户隐私数据应使用 S3 或 S4 等级 |
六、API 速查表
| 接口 | 说明 |
|---|---|
getRdbStore(context, config) |
获取 RdbStore 实例 |
executeSql(sql) |
执行不返回值的 SQL(如建表) |
insert(table, values) |
插入一行数据,返回行 ID |
delete(predicates) |
按条件删除数据 |
update(values, predicates) |
按条件更新数据 |
query(predicates, columns) |
按条件查询,返回 ResultSet |
deleteRdbStore(context, name) |
删除数据库文件 |
RdbPredicates 常用条件方法
| 方法 | 说明 |
|---|---|
equalTo(field, value) |
等于 |
notEqualTo(field, value) |
不等于 |
greaterThan(field, value) |
大于 |
lessThan(field, value) |
小于 |
like(field, value) |
模糊匹配 |
beginsWith(field, value) |
以某字符串开头 |
in(field, values) |
在集合中 |
orderByAsc(field) |
升序排列 |
orderByDesc(field) |
降序排列 |
limitAs(offset, count) |
分页限制 |
七、总结
通过关系型数据库实现数据持久化是 HarmonyOS 应用开发中处理结构化数据的核心方案。开发者只需掌握以下核心流程:
- 建库:通过
getRdbStore获取数据库实例 - 建表:通过
executeSql执行建表 SQL - 增删改查:使用
ValuesBucket+RdbPredicates+ 对应接口完成 CRUD - 资源释放:
ResultSet用完后务必调用close()
合理运用关系型数据库,可以让应用的数据管理更加高效、可靠。
更多推荐


所有评论(0)