HarmonyOS 使用关系型数据库进行增删改查
HarmonyOS 中的关系型数据库基于 SQLite 组件,提供了一套完整的对本地数据库进行管理的机制。它支持事务、索引、视图、触发器、外键、参数化查询和预编译 SQL 语句等特性。关系型数据库适用于存储包含复杂关系数据的场景,例如学生信息或雇员信息,这些数据之间有较强的对应关系。
操作关系型数据库的常见步骤
-
创建数据库和表:使用 relationalStore.getRdbStore 方法创建数据库,然后使用 executeSql 方法执行 SQL 语句来创建表。
-
插入数据:使用 insert 方法向表中插入数据。
-
批量插入数据:使用 batchInsert 方法向表中插入一组数据。
-
更新数据:使用 update 方法根据指定条件更新数据库中的数据。
-
删除数据:使用 delete 方法根据指定条件从数据库中删除数据。
-
查询数据:使用 query 方法根据指定条件查询数据库中的数据。
此外,HarmonyOS 还提供了 ResultSet 对象来访问查询结果,提供灵活的数据访问方式。
表的数据模型
定义Person
类,作为数据模型,用于表示数据库中的Person
表的行。
// 常量类配置信息
export class Person {
id: number
name: string
age: number
constructor(id: number, name: string, age: number) {
this.id = id
this.name = name
this.age = age
}
}
数据库配置信息
首先,定义数据库和表的配置信息,包括数据库名称、安全级别、表名称、创建表的SQL语句和列配置。
/**
* Rdb数据库配置。
* name:数据库名称
* securityLevel:数据库安全级别
*/
static readonly STORE_CONFIG: relationalStore.StoreConfig = {
name: 'database.db',
securityLevel: relationalStore.SecurityLevel.S1
};
/**
* 表配置信息
* tableName:表名称
* sqlCreate:创建表的语句
* columns:表的列项目
*/
static readonly PERSON_TABLE: PersonTable = {
tableName: 'personTable',
sqlCreate: 'CREATE TABLE IF NOT EXISTS personTable(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, ' +
'age INTEGER)',
columns: ['id', 'name', 'age']
};
/**
* Log tag.
*/
static readonly RDB_TAG = '[Debug.Rdb]';
static readonly TABLE_TAG = '[Debug.PersonTable]';
static readonly INDEX_TAG = '[Debug.Index]';
封装CRUD操作
封装了对关系型数据库(RDB)的一些基本操作,如创建、插入、删除、更新和查询数据。这个类使用了 @ohos.data.relationalStore 包。
import relationalStore from '@ohos.data.relationalStore';
import CommonConstants from '../constants/CommonConstants';
import Logger from '../utils/Logger';
export default class Rdb {
private rdbStore: relationalStore.RdbStore | null = null;
private tableName: string;
private sqlCreateTable: string;
private columns: Array<string>;
constructor(tableName: string, sqlCreateTable: string, columns: Array<string>) {
this.tableName = tableName;
this.sqlCreateTable = sqlCreateTable;
this.columns = columns;
}
getRdbStore(callback: Function = () => {
}) {
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'getRdbStore() has no callback!');
return;
}
if (this.rdbStore !== null) {
Logger.info(CommonConstants.RDB_TAG, 'The rdbStore exists.');
callback();
return
}
let context: Context = getContext(this) as Context;
relationalStore.getRdbStore(context, CommonConstants.STORE_CONFIG, (err, rdb) => {
if (err) {
Logger.error(CommonConstants.RDB_TAG, `gerRdbStore() failed, err: ${err}`);
return;
}
this.rdbStore = rdb;
this.rdbStore.executeSql(this.sqlCreateTable);
Logger.info(CommonConstants.RDB_TAG, 'getRdbStore() finished.');
callback();
});
}
insertData(data: relationalStore.ValuesBucket, callback: Function = () => {
}) {
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'insertData() has no callback!');
return;
}
let resFlag: boolean = false;
const valueBucket: relationalStore.ValuesBucket = data;
if (this.rdbStore) {
this.rdbStore.insert(this.tableName, valueBucket, (err, ret) => {
if (err) {
Logger.error(CommonConstants.RDB_TAG, `insertData() failed, err: ${err}`);
callback(resFlag);
return;
}
Logger.info(CommonConstants.RDB_TAG, `insertData() finished: ${ret}`);
callback(ret);
});
}
}
deleteData(predicates: relationalStore.RdbPredicates, callback: Function = () => {
}) {
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'deleteData() has no callback!');
return;
}
let resFlag: boolean = false;
if (this.rdbStore) {
this.rdbStore.delete(predicates, (err, ret) => {
if (err) {
Logger.error(CommonConstants.RDB_TAG, `deleteData() failed, err: ${err}`);
callback(resFlag);
return;
}
Logger.info(CommonConstants.RDB_TAG, `deleteData() finished: ${ret}`);
callback(!resFlag);
});
}
}
updateData(predicates: relationalStore.RdbPredicates, data: relationalStore.ValuesBucket, callback: Function = () => {
}) {
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'updateDate() has no callback!');
return;
}
let resFlag: boolean = false;
const valueBucket: relationalStore.ValuesBucket = data;
if (this.rdbStore) {
this.rdbStore.update(valueBucket, predicates, (err, ret) => {
if (err) {
Logger.error(CommonConstants.RDB_TAG, `updateData() failed, err: ${err}`);
callback(resFlag);
return;
}
Logger.info(CommonConstants.RDB_TAG, `updateData() finished: ${ret}`);
callback(!resFlag);
});
}
}
query(predicates: relationalStore.RdbPredicates, callback: Function = () => {
}) {
if (!callback || typeof callback === 'undefined' || callback === undefined) {
Logger.info(CommonConstants.RDB_TAG, 'query() has no callback!');
return;
}
if (this.rdbStore) {
this.rdbStore.query(predicates, this.columns, (err, resultSet) => {
if (err) {
Logger.error(CommonConstants.RDB_TAG, `query() failed, err: ${err}`);
return;
}
Logger.info(CommonConstants.RDB_TAG, 'query() finished.');
callback(resultSet);
resultSet.close();
});
}
}
}
具体表操作封装
使用了之前定义的 Rdb 类来执行具体的Person数据库操作。
import relationalStore from '@ohos.data.relationalStore';
import CommonConstants from '../../constants/CommonConstants';
import Rdb from '../rdb';
import { Person } from '../../bean/Person';
export default class PersonTable {
private accountTable = new Rdb(CommonConstants.PERSON_TABLE.tableName, CommonConstants.PERSON_TABLE.sqlCreate,
CommonConstants.PERSON_TABLE.columns);
constructor(callback: Function = () => {
}) {
this.accountTable.getRdbStore(callback);
}
getRdbStore(callback: Function = () => {
}) {
this.accountTable.getRdbStore(callback);
}
insert(person: Person, callback: Function) {
const valueBucket: relationalStore.ValuesBucket = generateBucket(person);
this.accountTable.insertData(valueBucket, callback);
}
deleteData(person: Person, callback: Function) {
let predicates = new relationalStore.RdbPredicates(CommonConstants.PERSON_TABLE.tableName);
predicates.equalTo('id', person.id);
this.accountTable.deleteData(predicates, callback);
}
updateData(person: Person, callback: Function) {
const valueBucket: relationalStore.ValuesBucket = generateBucket(person);
let predicates = new relationalStore.RdbPredicates(CommonConstants.PERSON_TABLE.tableName);
predicates.equalTo('id', person.id);
this.accountTable.updateData(predicates, valueBucket, callback);
}
// 查(查询的字段,回调,是否查询全部)
query(id: number, callback: Function, isAll: boolean = true) {
let predicates = new relationalStore.RdbPredicates(CommonConstants.PERSON_TABLE.tableName);
if (!isAll) {
predicates.equalTo('id', id);
}
this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
let count: number = resultSet.rowCount;
if (count === 0 || typeof count === 'string') {
console.log(`${CommonConstants.TABLE_TAG}` + 'Query no results!');
callback([]);
} else {
resultSet.goToFirstRow();
const result: Person[] = [];
for (let i = 0; i < count; i++) {
let tmp: Person = {
id: 0, name: '', age: 0
};
tmp.id = resultSet.getDouble(resultSet.getColumnIndex('id'));
tmp.name = resultSet.getString(resultSet.getColumnIndex('name'));
tmp.age = resultSet.getDouble(resultSet.getColumnIndex('age'));
result[i] = tmp;
resultSet.goToNextRow();
}
callback(result);
}
});
}
}
function generateBucket(person: Person): relationalStore.ValuesBucket {
let obj: relationalStore.ValuesBucket = {};
obj.name = person.name;
obj.age = person.age;
return obj;
}
使用示例
以下是如何使用上述封装的CRUD操作的示例。
insertPerson() {
this.newPerson =
new Person(
0,
CommonConstants.NAMES[Math.floor(Math.random() * CommonConstants.NAMES.length)] + '某',
Math.floor(Math.random() * 99
))
this.PersonTable.insert(this.newPerson, (id: number) => {
this.newPerson.id = id;
Logger.info(TAG, `id = ${id}`);
this.persons.push(this.newPerson)
});
}
queryAllPerson() {
this.PersonTable.getRdbStore(() => {
this.PersonTable.query(0, (result: Person[]) => {
this.persons.length = 0;
this.persons = result;
Logger.info(TAG, "persons = " + JSON.stringify(this.persons))
}, true);
});
}
updatePerson(item: Person, index: number) {
// 修改数据
this.newPerson = { ...item,
name: CommonConstants.NAMES[Math.floor(Math.random() * CommonConstants.NAMES.length)] + '某',
age: Math.floor(Math.random() * 99) }
this.PersonTable.updateData(this.newPerson, () => {
})
//替换
this.persons.splice(index, 1, this.newPerson)
}
deletePerson(item: Person, index: number) {
this.PersonTable.deleteData(item, () => {
this.persons.splice(index, 1)
})
}
结语
通过封装CRUD操作,可以显著提高代码的可读性和可维护性。同时,它也简化了数据库操作的复杂性,使得开发者可以更专注于业务逻辑的实现。