【鸿蒙HarmonyOS开发笔记】应用数据持久化之通过关系型数据库实现数据持久化

概述

关系型数据库(Relational Database,RDB)是一种基于关系模型来管理数据的数据库。关系型数据库基于SQLite组件提供了一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查等接口,也可以直接运行用户输入的SQL语句来满足复杂的场景需要。不支持Worker线程。

关系型数据库基于SQLite组件,适用于存储包含复杂关系数据的场景,比如一个班级的学生信息,需要包括姓名、学号、各科成绩等,又或者公司的雇员信息,需要包括姓名、工号、职位等,由于数据之间有较强的对应关系,复杂程度更高,此时需要使用关系型数据库来持久化保存数据。

基本概念

谓词:数据库中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用来定义数据库的操作条件。

结果集:指用户查询之后的结果集合,可以对数据进行访问。结果集提供了灵活的数据访问方式,可以更方便地拿到用户想要的数据

运作机制

关系型数据库对应用提供通用的操作接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的数据库特性,包括但不限于事务、索引、视图、触发器、外键、参数化查询和预编译SQL语句。


约束限制

系统默认日志方式是WAL(Write Ahead Log)模式,系统默认落盘方式是FULL模式。

数据库中连接池的最大数量是4个,用以管理用户的读操作。

为保证数据的准确性,数据库同一时间只能支持一个写操作。

当应用被卸载完成后,设备上的相关数据库文件及临时文件会被自动清除


导入模块

typescript 复制代码
import relationalStore from '@ohos.data.relationalStore'

该模块提供以下关系型数据库相关的常用功能:

RdbPredicates: 数据库中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用来定义数据库的操作条件。

RdbStore :提供管理关系数据库(RDB)方法的接口。

ResultSet:提供用户调用关系型数据库查询接口之后返回的结果集合。


relationalStore.getRdbStore

typescript 复制代码
getRdbStore(context: Context, config: StoreConfig): Promise<RdbStore>

获得一个相关的RdbStore,操作关系型数据库,用户可以根据自己的需求配置RdbStore的参数,然后通过RdbStore调用相关接口可以执行相关的数据操作,使用Promise异步回调。

参数列表

context:应用的上下文

config: 与此RDB存储相关的数据库配置。主要参数:name 数据库文件名,也是数据库唯一标识符,securityLevel设置数据库安全级别 详细请看官方文档

返回值

Promise<RdbStore>:Promise对象,返回RdbStore对象。

示例

typescript 复制代码
import UIAbility from '@ohos.app.ability.UIAbility'

class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage) {
    var store;
    const STORE_CONFIG = {
      name: "RdbTest.db",
      securityLevel: relationalStore.SecurityLevel.S1
    };
        
    let promise = relationalStore.getRdbStore(this.context, STORE_CONFIG);
    promise.then(async (rdbStore) => {
      store = rdbStore;
      console.info(`Get RdbStore successfully.`)
    }).catch((err) => {
      console.error(`Get RdbStore failed, code is ${err.code},message is ${err.message}`);
    })
  }
}

relationalStore.deleteRdbStore

typescript 复制代码
deleteRdbStore(context: Context, name: string): Promise<void>

使用指定的数据库文件配置删除数据库,使用Promise异步回调。

参数列表

context:应用的上下文

name: 数据库名称

返回值

Promise<void>:无返回结果的Promise对象。

示例

typescript 复制代码
import UIAbility from '@ohos.app.ability.UIAbility'

class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage){
    let promise = relationalStore.deleteRdbStore(this.context, "RdbTest.db");
    promise.then(()=>{
      console.info(`Delete RdbStore successfully.`);
    }).catch((err) => {
      console.error(`Delete RdbStore failed, code is ${err.code},message is ${err.message}`);
    })
  }
}

RdbStore

提供管理关系数据库( RDB)方法的接口。

在使用以下相关接口前,请使用executeSql接口初始化数据库表结构和相关数据


insert

typescript 复制代码
insert(table: string, values: ValuesBucket):Promise<number>

向目标表中插入一行数据,使用Promise异步回调。

参数列表

table:指定的目标表名

values: 表示要插入到表中的数据行

返回值

Promise<number>:Promise对象。如果操作成功,返回行ID;否则返回-1

示例

typescript 复制代码
const valueBucket = {
  "NAME": "Lisa",
  "AGE": 18,
  "SALARY": 100.5,
  "CODES": new Uint8Array([1, 2, 3, 4, 5]),
};
let promise = store.insert("EMPLOYEE", valueBucket);
promise.then((rowId) => {
  console.info(`Insert is successful, rowId = ${rowId}`);
}).catch((err) => {
  console.error(`Insert is failed, code is ${err.code},message is ${err.message}`);
})

batchInsert

typescript 复制代码
batchInsert(table: string, values: Array<ValuesBucket>):Promise<number>

向目标表中插入一组数据,使用Promise异步回调。

参数列表

table:指定的目标表名

values: 表示要插入到表中的一组数据

返回值

Promise<number>:Promise对象。如果操作成功,返回插入的数据个数;否则返回-1

示例

typescript 复制代码
const valueBucket1 = {
  "NAME": "Lisa",
  "AGE": 18,
  "SALARY": 100.5,
  "CODES": new Uint8Array([1, 2, 3, 4, 5])
};
const valueBucket2 = {
  "NAME": "Jack",
  "AGE": 19,
  "SALARY": 101.5,
  "CODES": new Uint8Array([6, 7, 8, 9, 10])
};
const valueBucket3 = {
  "NAME": "Tom",
  "AGE": 20,
  "SALARY": 102.5,
  "CODES": new Uint8Array([11, 12, 13, 14, 15])
};

let valueBuckets = new Array(valueBucket1, valueBucket2, valueBucket3);
let promise = store.batchInsert("EMPLOYEE", valueBuckets);
promise.then((insertNum) => {
  console.info(`batchInsert is successful, the number of values that were inserted = ${insertNum}`);
}).catch((err) => {
  console.error(`batchInsert is failed, code is ${err.code},message is ${err.message}`);
})

update

typescript 复制代码
update(values: ValuesBucket, predicates: RdbPredicates):Promise<number>

根据RdbPredicates的指定实例对象更新数据库中的数据,使用Promise异步回调。

参数列表

values:指示数据库中要更新的数据行。键值对与数据库表的列名相关联

predicates: RdbPredicates的实例对象指定的更新条件

返回值

Promise<number>:Promise对象。返回受影响的行数

示例

typescript 复制代码
const valueBucket = {
  "NAME": "Rose",
  "AGE": 22,
  "SALARY": 200.5,
  "CODES": new Uint8Array([1, 2, 3, 4, 5]),
};
let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
predicates.equalTo("NAME", "Lisa");
let promise = store.update(valueBucket, predicates);
promise.then(async (rows) => {
  console.info(`Updated row count: ${rows}`);
}).catch((err) => {
  console.error(`Updated failed, code is ${err.code},message is ${err.message}`);
})

delete

typescript 复制代码
delete(predicates: RdbPredicates):Promise<number>

根据RdbPredicates的指定实例对象从数据库中删除数据,使用Promise异步回调。

参数列表

predicates:RdbPredicates的实例对象指定的删除条件

返回值

Promise<number>:Promise对象。返回受影响的行数

示例

typescript 复制代码
let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
predicates.equalTo("NAME", "Lisa");
let promise = store.delete(predicates);
promise.then((rows) => {
  console.info(`Delete rows: ${rows}`);
}).catch((err) => {
  console.error(`Delete failed, code is ${err.code},message is ${err.message}`);
})

query

typescript 复制代码
query(predicates: RdbPredicates, columns?: Array<string>):Promise<ResultSet>

根据指定条件查询数据库中的数据,使用Promise异步回调。

参数列表

predicates:RdbPredicates的实例对象指定的查询条件

columns:表示要查询的列。如果值为空,则查询应用于所有列。

返回值

Promise<ResultSet>:Promise对象。如果操作成功,则返回ResultSet对象

示例

typescript 复制代码
let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
predicates.equalTo("NAME", "Rose");
let promise = store.query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"]);
promise.then((resultSet) => {
console.info(`ResultSet column names: ${resultSet.columnNames}`);
console.info(`ResultSet column count: ${resultSet.columnCount}`);
}).catch((err) => {
console.error(`Query failed, code is ${err.code},message is ${err.message}`);
})

querySql

typescript 复制代码
querySql(sql: string, bindArgs?: Array<ValueType>):Promise<ResultSet>

根据指定SQL语句查询数据库中的数据,使用Promise异步回调。

参数列表

sql:指定要执行的SQL语句

bindArgs:SQL语句中参数的值。当sql参数语句完整时,该参数不填。

返回值

Promise<ResultSet>:Promise对象。如果操作成功,则返回ResultSet对象

示例

typescript 复制代码
let promise = store.querySql("SELECT * FROM EMPLOYEE CROSS JOIN BOOK WHERE BOOK.NAME = 'sanguo'");
promise.then((resultSet) => {
  console.info(`ResultSet column names: ${resultSet.columnNames}`);
  console.info(`ResultSet column count: ${resultSet.columnCount}`);
}).catch((err) => {
  console.error(`Query failed, code is ${err.code},message is ${err.message}`);
})

ResultSet

提供通过查询数据库生成的数据库结果集的访问方法。结果集是指用户调用关系型数据库查询接口之后返回的结果集合,提供了多种灵活的数据访问方式,以便用户获取各项数据

使用说明

首先需要获取resultSet对象

typescript 复制代码
let resultSet = null;
let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
predicates.equalTo("AGE", 18);
let promise = store.query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"]);
promise.then((result) => {
  resultSet = result;
  console.info(`resultSet columnNames: ${resultSet.columnNames}`);
  console.info(`resultSet columnCount: ${resultSet.columnCount}`);
});

属性如下

columnNames

获取结果集中所有列的名称。


columnCount

获取结果集中的列数。


rowCount

获取结果集中的行数。


rowIndex

获取结果集当前行的索引。


isAtFirstRow

检查结果集是否位于第一行。


isAtLastRow

检查结果集是否位于最后一行。


isEnded

检查结果集是否位于最后一行之后。


isStarted

检查指针是否移动过。


isClosed

检查当前结果集是否关闭。


常用的方法

getColumnIndex

根据指定的列名获取列索引

typescript 复制代码
getColumnIndex(columnName: string): number

示例

typescript 复制代码
resultSet.goToFirstRow();
const id = resultSet.getLong(resultSet.getColumnIndex("ID"));
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));
const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));

goToNextRow

转到结果集的下一行

typescript 复制代码
goToNextRow(): boolean

示例

typescript 复制代码
let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
let promise = store.query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"]);
promise.then((resultSet) => {
resultSet.goToNextRow();
resultSet.close();
}).catch((err) => {
console.error(`query failed, code is ${err.code},message is ${err.message}`);
});

getBlob

以字节数组的形式获取当前行中指定列的值

typescript 复制代码
getBlob(columnIndex: number): Uint8Array
const codes = resultSet.getBlob(resultSet.getColumnIndex("CODES"));

getString

以字符串形式获取当前行中指定列的值

typescript 复制代码
getString(columnIndex: number): string
const name = resultSet.getString(resultSet.getColumnIndex("NAME"));

getLong

以Long形式获取当前行中指定列的值

typescript 复制代码
getLong(columnIndex: number): number
const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));

getDouble

以double形式获取当前行中指定列的值

typescript 复制代码
getDouble(columnIndex: number): number
const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));

isColumnNull

检查当前行中指定列的值是否为null,如果当前行中指定列的值为null,则返回true,否则返回false

typescript 复制代码
isColumnNull(columnIndex: number): boolean

示例

typescript 复制代码
const isColumnNull = resultSet.isColumnNull(resultSet.getColumnIndex("CODES"));

close

关闭结果集

typescript 复制代码
close(): void

示例

typescript 复制代码
let predicatesClose = new relationalStore.RdbPredicates("EMPLOYEE");
let promiseClose = store.query(predicatesClose, ["ID", "NAME", "AGE", "SALARY", "CODES"]);
promiseClose.then((resultSet) => {
resultSet.close();
}).catch((err) => {
console.error(`resultset close failed, code is ${err.code},message is ${err.message}`);
});
相关推荐
superman超哥16 分钟前
04 深入 Oracle 并发世界:MVCC、锁、闩锁、事务隔离与并发性能优化的探索
数据库·oracle·性能优化·dba
SuperHeroWu735 分钟前
【HarmonyOS】键盘遮挡输入框UI布局处理
华为·harmonyos·压缩·keyboard·键盘遮挡·抬起
engchina1 小时前
Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询
数据库·python·neo4j
engchina1 小时前
使用 Cypher 查询语言在 Neo4j 中查找最短路径
数据库·neo4j
尘浮生1 小时前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
威哥爱编程1 小时前
SQL Server 数据太多如何优化
数据库·sql·sqlserver
小华同学ai1 小时前
AJ-Report:一款开源且非常强大的数据可视化大屏和报表工具
数据库·信息可视化·开源
cuisidong19972 小时前
5G学习笔记三之物理层、数据链路层、RRC层协议
笔记·学习·5g
Acrelhuang2 小时前
安科瑞5G基站直流叠光监控系统-安科瑞黄安南
大数据·数据库·数据仓库·物联网
乌恩大侠2 小时前
5G周边知识笔记
笔记·5g