大家好,我是V哥。在 HarmonyOS NEXT 开发中,如何操作数据库,V 哥在测试中总结了以下学习代码,分享给你,如何想要系统学习鸿蒙开发,可以了解一下 V 哥最近刚刚上架出版的 《HarmonyOS 鸿蒙开发之路 卷2 从入门到应用篇》,V 哥在这本书里系统的介绍纯血鸿蒙的细枝末节,可以让零基础的朋友快速上手鸿蒙应用开发。

在鸿蒙开发中,系统 API 提供了基于SQLite组件的一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查等接口,也可以直接运行用户输入的SQL语句来满足复杂的场景需要。支持通过ResultSet.getSendableRow方法获取Sendable数据,进行跨线程传递。
这里要注意一下,为保证插入并读取数据成功,建议一条数据不超过2MB。如果数据超过2MB,插入操作将成功,读取操作将失败。
大数据量场景下查询数据可能会导致耗时长甚至应用卡死,如有相关操作可参考文档批量数据写数据库场景,且有建议如下:
- 单次查询数据量不超过5000条。
- 在TaskPool中查询。
- 拼接SQL语句尽量简洁。
- 合理地分批次查询。
该模块提供以下关系型数据库相关的常用功能:
- RdbPredicates:数据库中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用来定义数据库的操作条件。
- RdbStore:提供管理关系数据库(RDB)方法的接口。
- ResultSet:提供用户调用关系型数据库查询接口之后返回的结果集合。
- Transaction:提供管理事务对象的接口。
案例代码
接下来,V 哥通一个完整案例来介绍如何使用。
typescript
import relationalStore from '@ohos.data.relationalStore';
import promptAction from '@ohos.promptAction';
@Entry
@Component
struct RdbStoreExample {
@State userList: Array<{ id: number; name: string; age: number }> = [];
@State nameInput: string = '';
@State ageInput: string = '';
private rdbStore: relationalStore.RdbStore | null = null;
private rdbConfig: relationalStore.RdbStoreConfig = {
name: 'UserData.db',
securityLevel: relationalStore.SecurityLevel.S1
};
private CREATE_TABLE_USER =
'CREATE TABLE IF NOT EXISTS User (' +
'id INTEGER PRIMARY KEY AUTOINCREMENT, ' +
'name TEXT NOT NULL, ' +
'age INTEGER NOT NULL)';
aboutToAppear() {
this.openRdbStore();
}
aboutToDisappear() {
this.closeRdbStore();
}
// 打开数据库
async openRdbStore() {
try {
this.rdbStore = await relationalStore.getRdbStore(this.rdbConfig, 1,
(version: number, rdbStore: relationalStore.RdbStore) => {
if (version === 1) {
rdbStore.executeSql(this.CREATE_TABLE_USER, []);
}
});
await this.queryUsers();
} catch (error) {
console.error(`Failed to open RDB store: ${error}`);
promptAction.showToast({ message: '数据库打开失败' });
}
}
// 关闭数据库
async closeRdbStore() {
if (this.rdbStore) {
try {
await this.rdbStore.close();
this.rdbStore = null;
} catch (error) {
console.error(`Failed to close RDB store: ${error}`);
}
}
}
// 插入数据
async insertUser() {
if (!this.nameInput || !this.ageInput) {
promptAction.showToast({ message: '请输入姓名和年龄' });
return;
}
try {
const valuesBucket = {
name: this.nameInput,
age: parseInt(this.ageInput)
};
const id = await this.rdbStore?.insert('User', valuesBucket);
if (id && id > 0) {
promptAction.showToast({ message: '插入成功' });
await this.queryUsers();
this.nameInput = '';
this.ageInput = '';
}
} catch (error) {
console.error(`Failed to insert data: ${error}`);
promptAction.showToast({ message: '插入失败' });
}
}
// 查询数据
async queryUsers() {
try {
const resultSet = await this.rdbStore?.querySql(
'SELECT * FROM User', []);
if (resultSet) {
const users = [];
resultSet.goToFirstRow();
while (!resultSet.isAtEnd()) {
users.push({
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
age: resultSet.getInt(resultSet.getColumnIndex('age'))
});
resultSet.goToNextRow();
}
this.userList = users;
resultSet.close();
}
} catch (error) {
console.error(`Failed to query data: ${error}`);
promptAction.showToast({ message: '查询失败' });
}
}
// 更新数据
async updateUser(id: number, name: string, age: number) {
try {
const valuesBucket = {
name: name,
age: age
};
const conditions = new relationalStore.RdbStorePredicates('User');
conditions.equalTo('id', id.toString());
const rowsAffected = await this.rdbStore?.update(
valuesBucket, conditions);
if (rowsAffected && rowsAffected > 0) {
promptAction.showToast({ message: '更新成功' });
await this.queryUsers();
}
} catch (error) {
console.error(`Failed to update data: ${error}`);
promptAction.showToast({ message: '更新失败' });
}
}
// 删除数据
async deleteUser(id: number) {
try {
const conditions = new relationalStore.RdbStorePredicates('User');
conditions.equalTo('id', id.toString());
const rowsAffected = await this.rdbStore?.delete(conditions);
if (rowsAffected && rowsAffected > 0) {
promptAction.showToast({ message: '删除成功' });
await this.queryUsers();
}
} catch (error) {
console.error(`Failed to delete data: ${error}`);
promptAction.showToast({ message: '删除失败' });
}
}
build() {
Column() {
// 输入表单
Column() {
Input({
placeholder: '请输入姓名',
type: InputType.Text
})
.width('100%')
.margin({ top: 10, bottom: 10 })
.onChange((value: string) => {
this.nameInput = value;
})
Input({
placeholder: '请输入年龄',
type: InputType.Number
})
.width('100%')
.margin({ top: 10, bottom: 10 })
.onChange((value: string) => {
this.ageInput = value;
})
Button('添加用户')
.width('100%')
.onClick(() => {
this.insertUser();
})
}
.width('90%')
.margin({ top: 20, bottom: 20 })
// 用户列表
List() {
ForEach(this.userList, (user) => {
ListItem() {
Row() {
Column() {
Text(`姓名: ${user.name}`)
Text(`年龄: ${user.age}`)
}
.width('70%')
Column() {
Button('修改')
.onClick(() => {
const newName = promptAction.showPromptDialog({
message: '请输入新姓名',
defaultValue: user.name
});
const newAge = promptAction.showPromptDialog({
message: '请输入新年龄',
defaultValue: user.age.toString()
});
if (newName && newAge) {
this.updateUser(user.id, newName, parseInt(newAge));
}
})
Button('删除')
.onClick(() => {
this.deleteUser(user.id);
})
}
.width('30%')
}
.width('100%')
}
})
}
.width('90%')
.margin({ top: 10, bottom: 10 })
}
.width('100%')
.height('100%')
.padding(15)
}
}
下面来解释下这个示例:
-
首先要创建数据库配置并打开数据库,在
openRdbStore
方法里完成这些操作,创建了一个名为UserData.db
的数据库,还定义了建表语句。 -
插入数据时,使用
insert
方法,把姓名和年龄封装成valuesBucket
对象传进去,插入成功后会更新用户列表。 -
查询数据是通过
querySql
方法执行SQL语句,然后遍历结果集把数据存到userList
里。 -
更新数据用
update
方法,要先创建RdbStorePredicates
对象设置更新条件,根据ID来更新对应的记录。 -
删除数据也是先创建条件对象,然后调用
delete
方法,根据ID删除记录。 -
在界面上,提供了输入框让用户输入姓名和年龄,还有添加按钮,下面展示用户列表,每条记录都有修改和删除按钮。
操作技巧总结如下
- 打开和关闭数据库操作要在页面生命周期的合适时机进行,比如在
aboutToAppear
时打开,aboutToDisappear
时关闭。 - 执行数据库操作时一定要进行异常处理,避免程序崩溃。
- 使用预编译语句可以提高性能,特别是在批量操作的时候。
- 操作完成后要及时关闭
ResultSet
,释放资源。 - 合理设计表结构,设置合适的主键和索引能提升查询效率。
- 更新和删除操作记得设置好条件,防止误操作。
- 对于复杂查询,可以使用原生SQL语句,但要注意SQL注入问题。
好了,以上内容供你参考,学习鸿蒙开发,抢占市场风口,国产化之路,V 哥与你搀扶前行。