HarmonyOS 鸿蒙Next中如何使用RelationalStore实现数据库的增删改查(CRUD)操作?
HarmonyOS 鸿蒙Next中如何使用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 鸿蒙Next中如何使用RelationalStore实现数据库的增删改查(CRUD)操作?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中使用RelationalStore进行CRUD操作
在HarmonyOS Next中,使用RelationalStore进行CRUD操作的基本流程如下:
获取数据库实例
首先通过 getRdbStore 方法获取数据库实例。
创建表
使用 executeSql 方法执行CREATE语句来创建表。
插入数据
调用 insert 方法插入数据。
查询数据
使用 query 或 querySql 方法查询数据。
更新数据
调用 update 方法更新数据。
删除数据
使用 delete 方法删除数据。
注意事项
- 所有操作需在获取的RdbStore实例上完成。
- 注意处理异步回调。
在HarmonyOS Next中,使用RelationalStore进行CRUD操作的核心流程如下:
1. 数据库初始化
首先在module.json5中声明权限:
"requestPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
然后初始化RdbStore:
import { relationalStore } from '@kit.ArkData';
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'MyApplication.db',
securityLevel: relationalStore.SecurityLevel.S1
};
let rdbStore: relationalStore.RdbStore | undefined = undefined;
// 初始化数据库
async function initRdbStore(context: Context) {
try {
rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
// 创建表
const sql = `CREATE TABLE IF NOT EXISTS user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER
)`;
await rdbStore.executeSql(sql);
} catch (err) {
console.error(`Failed to init RdbStore. Code:${err.code}, message:${err.message}`);
}
}
2. Dao层设计
建议采用面向对象方式封装:
export class UserDao {
private rdbStore: relationalStore.RdbStore;
constructor(rdbStore: relationalStore.RdbStore) {
this.rdbStore = rdbStore;
}
// 插入数据
async insert(user: User): Promise<number> {
const valueBucket: relationalStore.ValuesBucket = {
'name': user.name,
'age': user.age
};
try {
return await this.rdbStore.insert('user', valueBucket);
} catch (err) {
console.error(`Failed to insert data. Code:${err.code}, message:${err.message}`);
return -1;
}
}
// 查询数据
async queryAll(): Promise<User[]> {
const predicates = new relationalStore.RdbPredicates('user');
try {
const resultSet = await this.rdbStore.query(predicates, ['id', 'name', 'age']);
return this.convertResultSetToUsers(resultSet);
} catch (err) {
console.error(`Failed to query data. Code:${err.code}, message:${err.message}`);
return [];
}
}
// 更新数据
async update(user: User): Promise<number> {
const predicates = new relationalStore.RdbPredicates('user');
predicates.equalTo('id', user.id);
const valueBucket: relationalStore.ValuesBucket = {
'name': user.name,
'age': user.age
};
try {
return await this.rdbStore.update(valueBucket, predicates);
} catch (err) {
console.error(`Failed to update data. Code:${err.code}, message:${err.message}`);
return 0;
}
}
// 删除数据
async delete(id: number): Promise<number> {
const predicates = new relationalStore.RdbPredicates('user');
predicates.equalTo('id', id);
try {
return await this.rdbStore.delete(predicates);
} catch (err) {
console.error(`Failed to delete data. Code:${err.code}, message:${err.message}`);
return 0;
}
}
// 结果集转换
private convertResultSetToUsers(resultSet: relationalStore.ResultSet): User[] {
const users: User[] = [];
while (resultSet.goToNextRow()) {
const user = new User();
user.id = resultSet.getLong(resultSet.getColumnIndex('id'));
user.name = resultSet.getString(resultSet.getColumnIndex('name'));
user.age = resultSet.getLong(resultSet.getColumnIndex('age'));
users.push(user);
}
resultSet.close();
return users;
}
}
3. 实体类定义
export class User {
id: number = 0;
name: string = '';
age: number = 0;
}
4. 异步处理
所有RelationalStore操作都是异步的,需要使用async/await或Promise:
// 使用示例
async function demo() {
await initRdbStore(getContext(this));
const userDao = new UserDao(rdbStore!);
// 插入
const newUser = new User();
newUser.name = '张三';
newUser.age = 25;
const insertId = await userDao.insert(newUser);
// 查询
const users = await userDao.queryAll();
// 更新
if (users.length > 0) {
users[0].name = '李四';
await userDao.update(users[0]);
}
// 删除
if (insertId > 0) {
await userDao.delete(insertId);
}
}
关键点:
- 使用
RdbPredicates构建查询条件 - 通过
ValuesBucket进行数据绑定 - 结果集操作后必须调用
close()释放资源 - 所有数据库操作都需要异常处理
- 确保在UI线程外执行耗时操作
这种设计模式清晰分离了数据访问逻辑,便于维护和扩展。

