写点什么

OpenHarmony 关系型数据库 [1]

作者:白晓明
  • 2023-03-24
    宁夏
  • 本文字数:5236 字

    阅读完需:约 17 分钟

OpenHarmony关系型数据库[1]

1 概述

关系型数据库(Relational Database, 以下简称 RDB)是一种基于关系模型来管理数据的数据库,是在 SQLite 基础上提供一套完整的对本地数据库进行管理的机制,为开发者提供无需编写原生 SQL 语句即可实现数据增、删、改、查等接口,同时开发者也可以直接运行原生 SQL 语句来满足复杂的场景需要。关系型数据库在应用卸载之后,才会被自动清除。

2 运作机制

RDB 对外提供通用的接口,底层使用 SQLite 作为持久化存储引擎,支持 SQLite 具有的所有数据库特性。SQLite 是一个进程内的库,具有自给自足、无服务、零配置、事务性特性的 SQL 数据库引擎。RDB 包括但不限于事务、索引、视图、触发器、外键、参数化查询和预编译 SQL 语句。

3 使用场景

  • 通讯录

  • 记事本

  • 计算器历史记录

  • App 用户登录信息

  • App 主题

  • ...

4 流程

5 详细步骤

RDB 对开发者提供的接口大部分为异步接口,均有callbackPromise两种返回形式,接下来将会一一介绍。

5.1 导入模块

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

5.2 配置数据库相关信息

创建数据库时需要配置数据库相关信息,RDB 提供管理关系型数据库配置的StoreConfig接口,其参数如表 5-1 所示:

表 5-1 关系型数据库配置参数

表 5-2 数据库的安全级别枚举


const store_config = {    name: "RdbSample.db",    securityLevel: relationalStore.SecurityLevel.S4,    encrypt: true}
复制代码

5.3 创建数据库

和 MySQL、Oracle 等数据库类似,在使用之前需要先创建数据库,RDB 提供了getRdbStore()方法用于创建数据库,该方法需要传入应用上下文Context和数据库配置信息StoreConfig两个参数,该方法有callbackPromise两种返回形式,如表 5-3 所示。表 5-3 数据库创建方法


// callback形式relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, rdbStore) => {  if (err) {    Log.error(TAG, "Get RdbStore fialed, err: " + JSON.stringify(err))    return;  }  // rdbStore相关操作  Log.info(TAG, "Get RdbStore successfully.");})
// Promise形式relationalStore.getRdbStore(this.context, STORE_CONFIG).then((rdbStore) => {  // rdbStore相关操作  Log.info(TAG, "Get RdbStore successfully.");}).catch((err) => {  Log.error(TAG, "Get RdbStore fialed, err: " + JSON.stringify(err))})
复制代码

注:RDB 不仅提供了数据库创建的方法,同时还提供了删除数据库方法,可以调用deleteRdbStore()方法进行数据库删除,使用方式和getRdbStore()方法类似。

5.4 数据表操作

创建数据库后,获取到RdbStore实例。RdbStore提供管理 RDB 方法的接口,在使用其增、删、改、查等接口之前,需要使用executeSql接口初始化数据表结构和相关数据。

5.4.1 创建数据表

executeSql()方法执行包含指定参数但不返回值得 SQL 语句,有callbackPromise两种形式,如表 5-4 所示。

表 5-4 创建数据表方法

注:表中的ValueType用于表示允许的数据字段类型,当前仅支持表示值类型为数字的number,表示值类型为字符的string,表示值类型为布尔值的boolean

const sql = "CREATE TABLE IF NOT EXISTS USER (ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME TEXT NOT NULL, PASSWORD TEXT NOT NULL)"// callback形式rdbStore.executeSql(sql, null, (err) {  if (err) {    Log.error(TAG, "ExecuteSql failed, err: " + JSON.stringify(err));    return;  }  Log.info(TAG, "Create table done.");})// Promise形式rdbStore.executeSql(sql, null).then(() => {  Log.info(TAG, "Create table done.");}).catch((err) => {  Log.error(TAG, "ExecuteSql failed, err: " + JSON.stringify(err));})
复制代码

5.4.2 新增数据

RdbStore提供了单条数据插入和批量数据插入两种为数据表新增数据的方法,如表 5-5 所示。

表 5-5 新增数据方法

注:表 5-5 中ValuesBucket是用于存储键值对的类型,其键为string类型,值类型可为ValueType|Uint8Array|null

const tableName = "USER";const valueBacket = {  "USERNAME": "Admin",  "PASSWORD": "123456"}// insert callback形式rdbStore.insert(tableName, valueBucket, (err, rowId) => {  if (err) {    Log.error(TAG, "Insert data failed, err: " + JSON.stringify(err));    return;  }  Log.info(TAG, "Insert data successful, rowId = " + rowId);})// insert Promise形式rdbStore.insert(tableName, valueBucket).then((rowId) => {  Log.info(TAG, "Insert data successful, rowId = " + rowId);}).catch((err) => {  Log.error(TAG, "Insert data failed, err: " + JSON.stringify(err));})
const valueBuckets = [{  "USERNAME": "aaa",  "PASSWORD": "123456"}, {  "USERNAME": "bbb",  "PASSWORD": "123456"}]// batchInsert callback形式rdbStore.batchInsert(tableName, valueBuckets, (err, count) => {  if (err) {    Log.error(TAG, "batchInsert data failed, err: " + JSON.stringify(err));    return;  }  Log.info(TAG, "batchInsert data successful, count = " + count);})// batchInsert Promise形式rdbStore.batchInsert(tableName, valueBuckets).then((count) => {  Log.info(TAG, "batchInsert data successful, count = " + count);}).catch((err) => {  Log.error(TAG, "batchInsert data failed, err: " + JSON.stringify(err));})
复制代码

5.4.3 更新数据

RdbStore提供了根据RdbPredicates指定实例对象和根据DataSharePredicates指定实例对象两种方式更新数据表中的数据,两种方式均有callbackPromise形式,如表 5-6 所示。

RdbPredicatesDataSharePredicates均用于数据表中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用于定义数据表的操作条件。如设置根据账号查找用户信息的条件,或者根据账号修改用户密码的条件。两者区别在于使用前者需要先指定操作的数据表名称,同时前者为分布式数据操作做了扩充。使用后者需要导入新模块import dataSharePredicates from '@ohos.data.dataSharePredicates';

表 5-6 更新数据方法


const tableName = "USER";const valueBucket = {  "USERNAME": "aaa",  "PASSWORD": "123456789"}
// RdbPredicateslet predicates = new relationalStore.RdbPredicates(tableName);predicates.equalTo("USERNAME", "aaa");// update callback形式rdbStore.update(valueBucket, predicates, (err, rows) => {  if (err) {    Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));    return;  }  Log.info(TAG, "Updated row count: " + rows);})// update Promise形式rdbStore.update(valueBucket, predicates).then((rows) => {  Log.info(TAG, "Updated row count: " + rows);}).catch((err) => {  Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));})
// DataSharePredicateslet predicates = new dataSharePredicates.DataSharePredicates();predicates.equalTo("USERNAME", "aaa");// update callback形式rdbStore.update(tableName, valueBucket, predicates, (err, rows) => {  if (err) {    Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));    return;  }  Log.info(TAG, "Updated row count: " + rows);})// update Promise形式rdbStore.update(tableName, valueBucket, predicates).then((rows) => {  Log.info(TAG, "Updated row count: " + rows);}).catch((err) => {  Log.error(TAG, "Updated failed, err: " + JSON.stringify(err));})
复制代码

5.4.4 查询数据

数据表数据的查询和更新相似,RdbStore也提供了RdbPredicatesDataSharePredicates两种方式,如表 5-7 所示。不同之处在于返回的结果不同,更新数据返回受影响的行数,查询数据返回的数据结果集ResultSet,关于结果集详细讲解将在下一节介绍。

表 5-7 查询数据方法


const tableName = "USER";// RdbPredicateslet predicates = new relationalStore.RdbPredicates(tableName);predicates.equalTo("USERNAME", "aaa");// query callback形式rdbStore.query(predicates, null, (err, resultSet) => {  if (err) {    Log.error(TAG, "Query failed, err: " + JSON.stringify(err));    return;  }  Log.info(TAG, "Query successful.");  Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);})// query Promise形式rdbStore.query(predicates, null).then((resultSet) => {  Log.info(TAG, "Query successful.");  Log.info(TAG, "ResultSet column count: " + resultSet.columnCoun}).catch((err) => {    Log.error(TAG, "Query failed, err: " + JSON.stringify(err));})
// DataSharePredicateslet predicates = new dataSharePredicates.DataSharePredicates();predicates.equalTo("USERNAME", "aaa");// query callback形式rdbStore.query(tableName, predicates, null, (err, resultSet) => {  if (err) {    Log.error(TAG, "Query failed, err: " + JSON.stringify(err));    return;  }  Log.info(TAG, "Query successful.");  Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);})// query Promise形式rdbStore.query(tableName, predicates, null).then((resultSet) => {  Log.info(TAG, "Query successful.");  Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);}).catch((err) => {    Log.error(TAG, "Query failed, err: " + JSON.stringify(err));})
复制代码

5.4.5 删除数据

表 5-8 删除数据方法


const tableName = "USER";// RdbPredicateslet predicates = new relationalStore.RdbPredicates(tableName);predicates.equalTo("USERNAME", "aaa");// delete callbackrdbStore.delete(predicates, (err, rows) => {  if (err) {    Log.error(TAG, "Delete failed, err: " + JSON.string(err));    return;  }  Log.info(TAG, "Delete rows: " + rows);})// delete PromiserdbStore.delete(predicates).then((rows) => {  Log.info(TAG, "Delete rows: " + rows);}).catch((err) => {  Log.error(TAG, "Delete failed, err: " + JSON.string(err));})
// DataSharePredicateslet predicates = new dataSharePredicates.DataSharePredicates();predicates.equalTo("USERNAME", "aaa");// delete callbackrdbStore.delete(tableName, predicates, (err, rows) => {  if (err) {    Log.error(TAG, "Delete failed, err: " + JSON.string(err));    return;  }  Log.info(TAG, "Delete rows: " + rows);})// delete PromiserdbStore.delete(tableName, predicates).then((rows) => {  Log.info(TAG, "Delete rows: " + rows);}).catch((err) => {  Log.error(TAG, "Delete failed, err: " + JSON.string(err));})
复制代码

6 原生 SQL 操作数据表

RdbStore不仅提供了适用于增删改查简单易操作的接口方法,同时还支持原生 SQL 语句的操作。

  • querySql()方法支持使用指定 SQL 语句查询数据表中的数据

const sql = "select * from user";rdbStore.querySql(sql).then((resultSet) => {  Log.info(TAG, "Query successful.");  Log.info(TAG, "ResultSet column count: " + resultSet.columnCount);}).catch((err) => {    Log.error(TAG, "Query failed, err: " + JSON.stringify(err));})
复制代码

7 小节

当然RdbStore还提供了其他的方法,诸如在开始执行 SQL 语句之前开启事务的beginTransaction()方法、提交已执行的 SQL 语句的commit()方法、回滚已执行的 SQL 语句的rollBack()方法以及用于其他能力的方法。本节仅对 RDB 数据库的简单使用做了讲解,其中涉及到RdbPredicatesDataSharePredicatesResultSet相关的更多内容将在后续封装 RDB 工具类中详细介绍。

发布于: 刚刚阅读数: 3
用户头像

白晓明

关注

还未添加个人签名 2021-03-10 加入

还未添加个人简介

评论

发布
暂无评论
OpenHarmony关系型数据库[1]_关系型数据库_白晓明_InfoQ写作社区