【HarmonyOS开发】ArkTs关系型和非关系型数据库的存储封装

图片

前面使用了首选项的存储方式,因此将其他的两种存储方式(键值型数据库和关系型数据库)也学习一下,简单记录一下,并进行封装,方便后续使用。

1、效果预览

2、使用条件

2.1 键值型数据库

        键值型数据库实现数据持久化width=device-width,initial-scale=1.0icon-default.png?t=N7T8http://test.openharmony.cn:7780/pages/v4.0/zh-cn/application-dev/database/data-persistence-by-kv-store.md/

  • 设备协同数据库,针对每条记录,Key的长度≤896 Byte,Value的长度<4 MB。
  • 单版本数据库,针对每条记录,Key的长度≤1 KB,Value的长度<4 MB。

  • 每个应用程序最多支持同时打开16个键值型分布式数据库。

  • 键值型数据库事件回调方法中不允许进行阻塞操作,例如修改UI组件。

2.2 关系型数据库

关系型数据库实现数据持久化width=device-width,initial-scale=1.0icon-default.png?t=N7T8http://test.openharmony.cn:7780/pages/v4.0/zh-cn/application-dev/database/data-persistence-by-rdb-store.md/

  • 系统默认日志方式是WAL(Write Ahead Log)模式,系统默认落盘方式是FULL模式。
  • 数据库中连接池的最大数量是4个,用以管理用户的读操作。

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

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

  • ArkTS侧支持的基本数据类型:number、string、二进制类型数据、boolean。

  • 为保证插入并读取数据成功,建议一条数据不要超过2M。超出该大小,插入成功,读取失败。

3、核心API

3.1 键值型数据库

  • createKVManager(创建一个KVManager对象实例)

  • getKVStore(指定Options和storeId,创建并得到指定类型的KVStore数据库)

  • put(添加指定类型的键值对到数据库)

  • get(获取指定键的值)

  • delete(从数据库中删除指定键值的数据)

3.2 关系型数据库

  • getRdbStore(获得一个相关的RdbStore,操作关系型数据库)

  • executeSql(执行包含指定参数但不返回值的SQL语句)

  • deleteRdbStore(删除数据库)

  • insert(插入一行数据)

  • delete(从数据库中删除数据)

  • update(更新数据库中的数据)

  • query(根据指定条件查询数据库中的数据)

4、封装与调用

4.1 键值型数据库

4.1.1 封装

import distributedKVStore from '@ohos.data.distributedKVStore';const BUNDLE_NAME = "dbName_tengyu"let context = getContext(this)
// 数据库对象
let kvManager: distributedKVStore.KVManager | undefined = undefined;
// KVStore数据库
let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;class DistributedUtil {constructor() {this.createKeyValueDB();}async getKvManager(bundleName?: string) {const kvStoreConfig: distributedKVStore.KVManagerConfig = {context: context,bundleName: bundleName || BUNDLE_NAME};try {kvManager = distributedKVStore.createKVManager(kvStoreConfig);}catch (err) {console.error(`error:${err}`)}}// 创建并得到指定类型的KVStore数据库async createKeyValueDB(op?: distributedKVStore.Options) {if (kvManager === undefined) {this.getKvManager();}try {const options: distributedKVStore.Options = {// 当数据库文件不存在时是否创建数据库,默认为truecreateIfMissing: true,// 设置数据库文件是否加密,默认为false,即不加密encrypt: false,// 设置数据库文件是否备份,默认为true,即备份backup: false,// 设置数据库文件是否自动同步。默认为false,即手动同步autoSync: true,// kvStoreType不填时,默认创建多设备协同数据库kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,// 多设备协同数据库:kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,securityLevel: distributedKVStore.SecurityLevel.S1};kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', op || options, (err, store: distributedKVStore.SingleKVStore) => {if (err) {console.error(`Failed to get KVStore: Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in getting KVStore.');kvStore = store;});} catch (e) {console.error(`An unexpected error occurred. Code:${e.code},message:${e.message}`);}return kvStore;}// 删除指定键值的数据async deleteStoreData(key: string) {if (!kvStore) {return;}try {kvStore.delete(key, (err) => {if (err !== undefined) {console.error(`Failed to delete data. Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in deleting data.');});} catch (e) {console.error(`An unexpected error occurred. Code:${e.code},message:${e.message}`);}}// 向键值数据库中插入数据async putStoreData(key: string, value: any) {if (!key || !value) {return}if(!kvStore) {kvStore = await this.createKeyValueDB();}try {kvStore.put(key, value, (err) => {if (err !== undefined) {console.error(`Failed to put data. Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in putting data.');});} catch (e) {console.error(`An unexpected error occurred. Code:${e.code},message:${e.message}`);}}// 获取指定键的值async getStoreData(key: string) {if (!key) {return}if(!kvStore) {kvStore = await this.createKeyValueDB();}return new Promise((resolve, reject) => {try {kvStore.get(key, (err, data) => {if (err != undefined) {console.error(`Failed to get data. Code:${err.code},message:${err.message}`);reject(err)return;}resolve(data)});} catch (err) {reject(err)console.error('TAG', `Failed to get value, Cause: ${err}`)}});}
}export default new DistributedUtil();

4.1.2 调用

import distributedUtil from '../../utils/distributedStrong'// 向数据库新增数据
distributedUtil.putStoreData('test0011', JSON.stringify({name: 666,age: 32,date: '2023.06.26'
}))// 获取数据库中的数据
distributedUtil.getStoreData('test0011').then(res => {console.log('===获取数据库中的数据====', JSON.stringify(res))
})

4.2 关系型数据库

关系型数据库运作机制 

4.2.1 封装

import relationalStore from '@ohos.data.relationalStore';const DB_NAME = "RelationStoreDB.db"let context = getContext(this)
let store: relationalStore.RdbStore | undefined = undefined;class RelationalUtil {async getRdbStoreConfig(dbName?: string, config?: relationalStore.StoreConfig) {const STORE_CONFIG: relationalStore.StoreConfig = config || {// 数据库文件名name: dbName || DB_NAME,// 数据库安全级别securityLevel: relationalStore.SecurityLevel.S1,// 可选参数,指定数据库是否加密,默认不加密encrypt: false,};return STORE_CONFIG;}// 创建并得到指定类型的KVStore数据库async createDatabaseTable(sqlCreateTable: string) {const STORE_CONFIG = await this.getRdbStoreConfig();relationalStore.getRdbStore(context, STORE_CONFIG, (err, rdbStore: relationalStore.RdbStore) => {if (err) {console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);return;}console.info('Succeeded in getting RdbStore.');// 当数据库创建时,数据库默认版本为0store = rdbStore;store.executeSql(sqlCreateTable); // 创建数据表})}// 删除数据库async deleteDB(dbName: string = DB_NAME) {relationalStore.deleteRdbStore(context, dbName, (err) => {if (err) {console.error(`Failed to delete RdbStore. Code:${err.code}, message:${err.message}`);return;}console.info('Succeeded in deleting RdbStore.');});}// 向数据库中插入数据async insertDatas(tableName: string, valueBucket) {if (store != undefined) {(store as relationalStore.RdbStore).insert(tableName, valueBucket, (err, rowId: number) => {if (err) {console.error(`Failed to insert data. Code:${err.code}, message:${err.message}`);return;}console.info(`Succeeded in inserting data. rowId:${rowId}`);})}}// 对数据进行修改async updateDatas(tableName: string, valueBucket, key, val) {let predicates = new relationalStore.RdbPredicates(tableName); // 创建表tableName的predicatespredicates.equalTo(key, val); // 匹配表tableName中key为val的字段if (store != undefined) {(store as relationalStore.RdbStore).update(valueBucket, predicates, (err, rowId: number) => {if (err) {console.error(`Failed to insert data. Code:${err.code}, message:${err.message}`);return;}console.info(`Succeeded in inserting data. rowId:${rowId}`);})}}//根据谓词指定的查询条件查找数据async getDatas(tableName: string, atomArr: Array<string>, key: string, val: string | number) {let predicates = new relationalStore.RdbPredicates(tableName);predicates.equalTo(key, val);if (store != undefined) {return new Promise((resolve, reject) => {(store as relationalStore.RdbStore).query(predicates, atomArr, (err, resultSet) => {if (err) {console.error(`Failed to query data. Code:${err.code}, message:${err.message}`);reject(err);return;}resolve(resultSet);console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);})})}}
}export default new RelationalUtil();

4.2.2 调用

import relationalUtil from '../../utils/relationalStrong';
import { ValuesBucket } from '@ohos.data.ValuesBucket';const DB_NAME = 'testDB'
const TABLE_NAME = 'table1'
// 建库建表
const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)'; 
relationalUtil.createDatabaseTable(SQL_CREATE_TABLE, DB_NAME);// 删除数据库
relationalUtil.deleteDB(DB_NAME);// 新增数据
const valBucket: ValuesBucket = {'NAME': 111,'AGE': 222,'SALARY': 333,'CODES': 444,
};
relationalUtil.insertDatas(TABLE_NAME, valBucket);// 修改数据
relationalUtil.updateDatas(TABLE_NAME, valBucket, 'NAME', 'Test001Val');// 获取数据
relationalUtil.getDatas(TABLE_NAME, ['NAME', 'AGE', 'SALARY'], 'NAME', 'Test001Val');

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/222516.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Modbus-TCP数据帧

Modbus-TCP基于4种报文类型 MODBUS 请求是客户机在网络上发送用来启动事务处理的报文MODBUS 指示是服务端接收的请求报文MODBUS 响应是服务器发送的响应信息MODBUS 证实是在客户端接收的响应信息 Modbus-TCP报文: 报文头MBAP MBAP为报文头&#xff0c;长度为7字节&#xff0c…

CentOS操作学习(二)

上一篇学习了CentOS的常用指令CentOS指令学习-CSDN博客 现在我们接着学习 一、Vi编辑器 这是CentOS中自带的编辑器 三种模式 进入编辑模式后 i&#xff1a;在光标所在字符前开始插入a&#xff1a;在光标所在字符串后开始插入o&#xff1a;在光标所在行的下面另起一新行插入…

【排序算法】C语言实现选择排序与冒泡排序

文章目录 &#x1f680;前言&#x1f680;冒泡排序✈️冒泡排序的逻辑✈️冒泡排序coding &#x1f680;选择排序✈️选择排序的逻辑✈️选择排序coding &#x1f680;前言 这里是阿辉算法与数据结构专栏的第一篇文章&#xff0c;咱们就从排序算法开始讲起&#xff0c;排序算法…

freeswitch on debian docker

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 因为centos系统期限的原因&#xff0c;尝试在debian的docker上使用fs。 环境 docker engine&#xff1a;Version 24.0.6 debian docker&#xff1a;bullseye 11.8 freeswitch&#xff1a;v1.10.7 Debian准备 目前…

C语言之初识C语言

文章目录 前言一、什么是C语言二、第一个C语言程序三、数据类型四、变量&#xff0c;常量1、变量1.1 变量的命名1.2 变量的分类1.3 变量的使用1.4 变量的作用域和生命周期2、变量 五、字符串1. 概念2. 求解字符串的长度【strlen】3. 转义字符【含笔试题】 六、注释七、选择语句…

Docker 文件和卷 权限拒绝

一 创作背景 再复制Docker影像文件或访问Docker容器内已安装卷上的文件时我们常常会遇到&#xff1a;“权限被拒绝”的错误&#xff0c;在此&#xff0c;您将了解到为什么会出现“权限被拒绝”的错误以及如何解决这个问题。 二 目的 在深入探讨 Docker 容器中的 Permission De…

互操作性(Interoperability)如何影响着机器学习的发展?

互操作性&#xff08;Interoperability&#xff09;&#xff0c;也称为互用性&#xff0c;即两个系统之间有效沟通的能力&#xff0c;是机器学习未来发展中的关键因素。对于银行业、医疗和其他生活服务行业&#xff0c;我们期望那些用于信息交换的平台可以在我们需要时无缝沟通…

springboot+vue前后端分离的社区养老服务管理管理系统(有文档)

springbootvue前后端分离的社区养老服务管理管理系统。系统功能齐全&#xff0c;配置完成可运行&#xff0c;有文档&#xff0c;演示视频&#xff0c;配置说明&#xff0c;数据库文件&#xff0c;虚拟产品下单不退不换&#xff01; 技术&#xff1a;springbootmybatisplusmysql…

STM32的以太网外设+PHY(LAN8720)使用详解(6):以太网数据接收及发送

0 工具准备 1.野火 stm32f407霸天虎开发板 2.LAN8720数据手册 3.STM32F4xx中文参考手册1 以太网数据接收及发送 1.1 以太网数据接收&#xff08;轮询&#xff09; 1.1.1 检查是否接收到一帧完整报文 使用轮询的方式接收以太网数据是一种简单但是效率低下的方法&#xff0c;…

【Seata源码学习 】 篇二 TM与RM初始化过程

【Seata源码学习 】 篇二 TM与RM初始化过程 1.GlobalTransactionScanner 初始化 GlobalTransactionScanner 实现了InitializingBean 接口&#xff0c;在初始化后将执行自定义的初始化方法 io.seata.spring.annotation.GlobalTransactionScanner#afterPropertiesSet Override…

环境搭建及源码运行_java环境搭建_idea版本下载及安装

1、介绍 Idea是一款被广泛使用的Java集成开发环境&#xff0c;它提供了丰富的功能和工具来帮助开发人员更高效地编写和调试代码。作为一款开源软件&#xff0c;Idea不仅提供了基本的代码编辑、自动完成和调试功能&#xff0c;还支持大量的插件和扩展&#xff0c;可为开发人员提…

文件传输软件SecureFX mac支持多种协议

SecureFX mac是一款文件传输客户端&#xff0c;可在 Mac 操作系统上使用。它由 VanDyke Software 公司开发&#xff0c;旨在为用户提供安全、可靠、高效的文件传输服务。 SecureFX 支持多种协议&#xff0c;包括 SFTP、SCP、FTP、FTP over SSL/TLS 和 HTTP/S。它使用强大的加密…

Python代码示例 | 时间序列数据的组成

时间序列数据是以固定的时间间隔记录或收集的数据点序列。它是一种跟踪变量随时间演变的数据&#xff0c;如销售&#xff0c;股票价格&#xff0c;温度等。定期的时间间隔可以是每天&#xff0c;每周&#xff0c;每月&#xff0c;每季度或每年&#xff0c;数据通常表示为线图或…

Sublime Text 3配置 C# 开发环境

Sublime Text 3配置 C# 开发环境 一、引言二、主要内容1. 初识 Sublime Text 32. 初识 C#3. 接入 .NET Framework3.1 下载 .NET Framework3.2 环境变量配置 4. 配置 C# 开发环境5. 编写 C# 代码6. 运行 C# 代码 三、总结 一、引言 C# 是一种面向对象的编程语言&#xff0c;由微…

【华为数据之道学习笔记】6-5数据地图的核心价值

数据供应者与消费者之间往往存在一种矛盾&#xff1a;供应者做了大量的数据治理工作、提供了大量的数据&#xff0c;但数据消费者却仍然不满意&#xff0c;他们始终认为在使用数据之前存在两个重大困难。 1&#xff09;找数难 企业的数据分散存储在上千个数据库、上百万张物理表…

配置https环境

为什么要配置https环境 在使用 HTML5 的 API 时&#xff0c;很多 API 只能在 https 保证安全的情况下才能开启。这就要求我们在本地开发环境也能够配置 https&#xff0c;否则你需要每次部署到配有 https 的测试环境中才能看到预览效果&#xff0c;这对开发的敏捷度造成了极大…

项目进度管理:常用项目管理工具推荐

工欲善其事必先利其器&#xff0c;借助项目管理工具可以帮助项目经理更好的管理项目&#xff0c;起到事半功倍的效果。 使用项目管理工具来管理项目&#xff0c;有助于事情的快速落地&#xff0c;提升做事效率&#xff0c;也能让事情做的更周到全面 选择项目管理工具时可以参…

通过几个基本概念说一下为什么openGauss是当下之选?

Database、Schema、User都是数据库的基本概念&#xff0c;SQL标准中也有明确规范。但不同数据库的具体实现也不尽相同&#xff0c;有些甚至大相径庭。这就导致用户在做国产化选型和数据库迁移时可能会遇到种种困难。本文从这几个基本概念展开&#xff0c;说说为什么openGauss系…

数据结构之进阶二叉树(二叉搜索树和AVL树、红黑树的实现)超详细解析,附实操图和搜索二叉树的实现过程图

绪论​ “生命有如铁砧&#xff0c;愈被敲打&#xff0c;愈能发出火花。——伽利略”&#xff1b;本章主要是数据结构 二叉树的进阶知识&#xff0c;若之前没学过二叉树建议看看这篇文章一篇掌握二叉树&#xff0c;本章的知识从浅到深的对搜索二叉树的使用进行了介绍和对其底层…

linux 内核的 lru_list 的结构

在linux的slab分配的入口slab_alloc有一个传入参数lru&#xff0c;它的作用是使每个slab对象在unused&#xff0c;但可能后面继续使用的时候&#xff0c;不需要free&#xff0c;可以先放在lru_list上。lru_list的结构为&#xff1a; struct list_lru {struct list_lru_node *n…