#跟着坚果学鸿蒙# HarmonyOS 5 通过关系型数据库实现数据持久化开发指南
·
一、HarmonyOS 数据持久化概述
在移动应用开发中,数据持久化是核心需求之一。HarmonyOS 5 提供了多种数据持久化方案,其中关系型数据库因其强大的结构化数据管理能力,成为处理复杂数据的首选方案。
HarmonyOS 5 的关系型数据库基于 SQLite 引擎构建,具有以下特点:
- ACID 事务支持:保证数据操作的原子性、一致性、隔离性和持久性
- 丰富的查询功能:支持标准 SQL 语法和复杂查询
- 跨设备同步:结合分布式能力实现多设备数据一致性
- 高性能:针对移动设备优化的存储引擎
二、关系型数据库核心概念
2.1 基本组件
- RdbStore:数据库实例,提供增删改查接口
- **谓词(Predicates)**:定义数据操作条件
- **结果集(ResultSet)**:查询结果的集合
- Schema:数据库表结构定义
2.2 运作机制
HarmonyOS 关系型数据库采用分层架构:
应用层 → 关系型数据库API → SQLite引擎 → 存储文件
这种设计既保持了SQLite的高效,又提供了面向对象的接口。
三、完整开发示例:学生成绩管理系统
下面我们通过一个完整的学生成绩管理案例,演示如何使用关系型数据库。
3.1 创建数据库和表
首先定义学生表结构,包含学号、姓名和各科成绩:
// 导入关系型数据库模块
import { relationalStore } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
// 定义学生表结构
const STUDENT_SCHEMA = {
tableName: 'student',
columns: {
id: { // 学号为主键
name: 'id',
type: relationalStore.StoreType.INTEGER,
isPrimaryKey: true
},
name: {
name: 'name',
type: relationalStore.StoreType.STRING,
notNull: true
},
math: {
name: 'math',
type: relationalStore.StoreType.INTEGER,
defaultValue: 0
},
english: {
name: 'english',
type: relationalStore.StoreType.INTEGER,
defaultValue: 0
},
science: {
name: 'science',
type: relationalStore.StoreType.INTEGER,
defaultValue: 0
}
}
};
// 数据库配置
const config = {
name: 'grades.db', // 数据库文件名
securityLevel: relationalStore.SecurityLevel.S1 // 安全级别
};
// 创建或打开数据库
let rdbStore: relationalStore.RdbStore;
try {
relationalStore.getRdbStore(this.context, config, (err, store) => {
if (err) {
console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`);
return;
}
console.info('Succeeded in getting RdbStore.');
rdbStore = store;
// 创建学生表
rdbStore.createTable(STUDENT_SCHEMA.tableName, STUDENT_SCHEMA.columns, (err) => {
if (err) {
console.error(`Failed to create table. Code:${err.code},message:${err.message}`);
return;
}
console.info('Succeeded in creating table.');
});
});
} catch (err) {
const error = err as BusinessError;
console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
}
3.2 插入学生数据
添加几个学生记录到数据库:
// 插入单个学生记录
const insertStudent = (student: {
id: number,
name: string,
math: number,
english: number,
science: number
}) => {
const valueBucket = {
'id': student.id,
'name': student.name,
'math': student.math,
'english': student.english,
'science': student.science
};
rdbStore.insert(STUDENT_SCHEMA.tableName, valueBucket, (err, rowId) => {
if (err) {
console.error(`Failed to insert data. Code:${err.code},message:${err.message}`);
return;
}
console.info(`Succeeded in inserting data. rowId:${rowId}`);
});
}
// 批量插入示例数据
const students = [
{id: 1001, name: '张三', math: 85, english: 92, science: 78},
{id: 1002, name: '李四', math: 76, english: 88, science: 90},
{id: 1003, name: '王五', math: 92, english: 79, science: 85}
];
students.forEach(student => {
insertStudent(student);
});
3.3 查询学生成绩
实现按条件查询和排序功能:
// 查询所有学生并按总分降序排列
const queryAllStudents = () => {
const columns = ['id', 'name', 'math', 'english', 'science'];
const predicates = new relationalStore.RdbPredicates(STUDENT_SCHEMA.tableName);
predicates.orderByDesc('(math + english + science)'); // 按总分降序
rdbStore.query(predicates, columns, (err, resultSet) => {
if (err) {
console.error(`Failed to query data. Code:${err.code},message:${err.message}`);
return;
}
console.info('学生成绩排名:');
while (resultSet.goToNextRow()) {
const id = resultSet.getDouble(resultSet.getColumnIndex('id'));
const name = resultSet.getString(resultSet.getColumnIndex('name'));
const math = resultSet.getDouble(resultSet.getColumnIndex('math'));
const english = resultSet.getDouble(resultSet.getColumnIndex('english'));
const science = resultSet.getDouble(resultSet.getColumnIndex('science'));
const total = math + english + science;
console.info(`学号:${id} 姓名:${name} 数学:${math} 英语:${english} 科学:${science} 总分:${total}`);
}
resultSet.close(); // 关闭结果集
});
}
// 查询数学成绩大于80分的学生
const queryGoodAtMath = () => {
const columns = ['id', 'name', 'math'];
const predicates = new relationalStore.RdbPredicates(STUDENT_SCHEMA.tableName);
predicates.greaterThan('math', 80); // 数学>80
rdbStore.query(predicates, columns, (err, resultSet) => {
if (err) {
console.error(`Failed to query data. Code:${err.code},message:${err.message}`);
return;
}
console.info('数学优秀学生:');
while (resultSet.goToNextRow()) {
const id = resultSet.getDouble(resultSet.getColumnIndex('id'));
const name = resultSet.getString(resultSet.getColumnIndex('name'));
const math = resultSet.getDouble(resultSet.getColumnIndex('math'));
console.info(`学号:${id} 姓名:${name} 数学:${math}`);
}
resultSet.close();
});
}
3.4 更新和删除数据
实现成绩修改和学生记录删除功能:
// 更新学生成绩
const updateStudentGrade = (studentId: number, subject: string, newGrade: number) => {
const predicates = new relationalStore.RdbPredicates(STUDENT_SCHEMA.tableName);
predicates.equalTo('id', studentId);
const values = {
[subject]: newGrade
};
rdbStore.update(values, predicates, (err, rowsAffected) => {
if (err) {
console.error(`Failed to update data. Code:${err.code},message:${err.message}`);
return;
}
console.info(`Succeeded in updating data. rowsAffected:${rowsAffected}`);
});
}
// 删除学生记录
const deleteStudent = (studentId: number) => {
const predicates = new relationalStore.RdbPredicates(STUDENT_SCHEMA.tableName);
predicates.equalTo('id', studentId);
rdbStore.delete(predicates, (err, rowsAffected) => {
if (err) {
console.error(`Failed to delete data. Code:${err.code},message:${err.message}`);
return;
}
console.info(`Succeeded in deleting data. rowsAffected:${rowsAffected}`);
});
}
四、完整UI实现
下面我们将数据库操作与ArkUI结合,创建一个完整的学生成绩管理界面。
@Entry
@Component
struct StudentManager {
@State students: Array<{
id: number,
name: string,
math: number,
english: number,
science: number,
total: number
}> = [];
// 加载学生数据
loadStudents() {
const columns = ['id', 'name', 'math', 'english', 'science'];
const predicates = new relationalStore.RdbPredicates(STUDENT_SCHEMA.tableName);
predicates.orderByDesc('(math + english + science)');
rdbStore.query(predicates, columns, (err, resultSet) => {
if (err) {
console.error(`Failed to query data. Code:${err.code},message:${err.message}`);
return;
}
this.students = [];
while (resultSet.goToNextRow()) {
const id = resultSet.getDouble(resultSet.getColumnIndex('id'));
const name = resultSet.getString(resultSet.getColumnIndex('name'));
const math = resultSet.getDouble(resultSet.getColumnIndex('math'));
const english = resultSet.getDouble(resultSet.getColumnIndex('english'));
const science = resultSet.getDouble(resultSet.getColumnIndex('science'));
this.students.push({
id,
name,
math,
english,
science,
total: math + english + science
});
}
resultSet.close();
});
}
build() {
Column() {
// 标题
Text('学生成绩管理系统')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 });
// 刷新按钮
Button('刷新数据')
.onClick(() => {
this.loadStudents();
})
.width('90%')
.margin({ bottom: 20 });
// 学生列表
List({ space: 10 }) {
ForEach(this.students, (student) => {
ListItem() {
Column() {
Row() {
Text(`学号: ${student.id}`)
.fontSize(16)
.fontWeight(FontWeight.Bold);
Text(student.name)
.fontSize(16)
.margin({ left: 20 });
}
.width('100%')
.justifyContent(FlexAlign.Start);
Row() {
Text(`数学: ${student.math}`)
.fontColor(Color.Red);
Text(`英语: ${student.english}`)
.fontColor(Color.Blue)
.margin({ left: 10 });
Text(`科学: ${student.science}`)
.fontColor(Color.Green)
.margin({ left: 10 });
Text(`总分: ${student.total}`)
.fontWeight(FontWeight.Bold)
.margin({ left: 10 });
}
.width('100%')
.margin({ top: 5 });
}
.padding(10)
.width('100%')
.borderRadius(10)
.backgroundColor('#f5f5f5')
}
}, student => student.id.toString())
}
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
.padding(10)
.onAppear(() => {
this.loadStudents(); // 页面显示时加载数据
})
}
}
五、高级特性与最佳实践
5.1 事务处理
对于需要原子性的一组操作,使用事务保证数据一致性:
const transferScores = (fromId: number, toId: number, points: number) => {
rdbStore.beginTransaction();
try {
// 减少源学生分数
const deductPredicates = new relationalStore.RdbPredicates(STUDENT_SCHEMA.tableName);
deductPredicates.equalTo('id', fromId);
const deductValues = {
'math': relationalStore.RdbStore.getSql('math - ?', [points])
};
rdbStore.update(deductValues, deductPredicates);
// 增加目标学生分数
const addPredicates = new relationalStore.RdbPredicates(STUDENT_SCHEMA.tableName);
addPredicates.equalTo('id', toId);
const addValues = {
'math': relationalStore.RdbStore.getSql('math + ?', [points])
};
rdbStore.update(addValues, addPredicates);
rdbStore.commit(); // 提交事务
console.info('分数转移成功');
} catch (err) {
rdbStore.rollback(); // 回滚事务
const error = err as BusinessError;
console.error(`分数转移失败. Code:${error.code},message:${error.message}`);
}
}
5.2 数据库升级
当需要修改表结构时,通过版本升级实现:
const upgradeDatabase = (context: Context) => {
const config = {
name: 'grades.db',
securityLevel: relationalStore.SecurityLevel.S1,
version: 2, // 新版本号
onUpgrade: (store, oldVersion, newVersion) => {
// 从版本1升级到版本2:添加历史成绩表
if (oldVersion === 1 && newVersion === 2) {
const HISTORY_SCHEMA = {
tableName: 'history_scores',
columns: {
id: {
name: 'id',
type: relationalStore.StoreType.INTEGER,
isPrimaryKey: true
},
student_id: {
name: 'student_id',
type: relationalStore.StoreType.INTEGER,
notNull: true
},
exam_date: {
name: 'exam_date',
type: relationalStore.StoreType.STRING
},
scores: {
name: 'scores',
type: relationalStore.StoreType.STRING // JSON格式存储各科成绩
}
}
};
store.createTable(HISTORY_SCHEMA.tableName, HISTORY_SCHEMA.columns);
}
}
};
relationalStore.getRdbStore(context, config, (err, store) => {
if (err) {
console.error(`Failed to upgrade database. Code:${err.code},message:${err.message}`);
return;
}
console.info('Database upgraded successfully');
});
}
5.3 性能优化建议
- 批量操作:使用
executeBatch进行批量插入/更新 - 索引优化:为常用查询条件创建索引
- 合理分页:大数据量查询使用
limit和offset - 异步处理:耗时操作放在 TaskPool 中执行
六、总结
本文详细介绍了如何在 HarmonyOS 5 中使用关系型数据库实现数据持久化,从基本概念到完整实现,涵盖了:
- 数据库创建和表结构设计
- 增删改查等基本操作
- 事务处理和数据库升级
- 与ArkUI框架的集成
- 性能优化最佳实践
关系型数据库是HarmonyOS应用开发中处理结构化数据的强大工具,掌握这些技能将帮助你构建更健壮、高效的应用程序。随着HarmonyOS生态的发展,关系型数据库在多设备协同、数据安全等方面还将提供更多高级特性,值得开发者持续关注和学习。
更多推荐


所有评论(0)