当前位置: 首页 > news >正文

【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');

相关文章:

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

前面使用了首选项的存储方式&#xff0c;因此将其他的两种存储方式&#xff08;键值型数据库和关系型数据库&#xff09;也学习一下&#xff0c;简单记录一下&#xff0c;并进行封装&#xff0c;方便后续使用。 1、效果预览 2、使用条件 2.1 键值型数据库 键值型数据库实现数据…...

Latex编译出来的pdf文件缺少参考文献和交叉引用

参考文件通常需要在首次编译后&#xff0c;再次编译添加 依次执行下面的命令即可&#xff1a; xelatex main.tex main.tex为需要编译的主tex文件 biber mainxelatex main.tex 如果编译过程中遇到错误&#xff0c;请删除所有辅助文件和已打开的pdf文件后重试 辅助文件包括&#…...

sql_lab靶场搭建以及存在的一些问题

sql_lab靶场搭建问题 首先检查小皮版本 把小皮改到5.3.29版本如果没有可以直接点击更多版本进行选择安装 当版本不对时则会暴出这种错误 SETTING UP THE DATABASE SCHEMA AND POPULATING DATA IN TABLES: Fatal error: Uncaught Error: Call to undefined function mysql_co…...

Https接口调用问题

使用场景: 因为项目需要爬点接口数据, 接口是https, 在网上找的笔记整理了一下. 仅供参考 1. 调用Https的Get方法 /*** 只需要url** param url* return*/public static String doGetForHTML(String url) {return doGetForHTML(url, null);}/*** param url 请求地址* para…...

CSS自适应分辨率 amfe-flexible 和 postcss-pxtorem:大屏高宽自适应问题

前言 继上篇《CSS自适应分辨率 amfe-flexible 和 postcss-pxtorem》。 发现一个有趣的问题&#xff0c;文件 rem.js 中按照宽度设置自适应&#xff0c;适用于大多数页面&#xff0c;但当遇到大屏就不那么合适了。 问题 使用宽度&#xff0c;注意代码第2 和 4 行&#xff1a;…...

SQL面试题挑战01:打折日期交叉问题

目录 问题&#xff1a;SQL解答&#xff1a;第一种方式&#xff1a;第二种方式&#xff1a; 问题&#xff1a; 如下为某平台的商品促销数据&#xff0c;字段含义分别为品牌名称、打折开始日期、打折结束日期&#xff0c;现在要计算每个品牌的打折销售天数&#xff08;注意其中的…...

三大主流前端框架介绍及选型

在前端项目中&#xff0c;可以借助某些框架&#xff08;如React、Vue、Angular等&#xff09;来实现组件化开发&#xff0c;使代码更容易复用。此时&#xff0c;一个网页不再是由一个个独立的HTML、CSS和JavaScript文件组成&#xff0c;而是按照组件的思想将网页划分成一个个组…...

云原生消息流系统 Apache Pulsar 在腾讯云的大规模生产实践

导语 由 InfoQ 主办的 Qcon 全球软件开发者大会北京站上周已精彩落幕&#xff0c;腾讯云中间件团队的冉小龙参与了《云原生机构设计与音视频技术应用》专题&#xff0c;带来了以《云原生消息流系统 Apache Pulsar 在腾讯云的大规模生产实践》为主题的精彩演讲&#xff0c;在本…...

【LeetCode刷题】--245.最短单词距离III

245.最短单词距离III class Solution {public int shortestWordDistance(String[] wordsDict, String word1, String word2) {int len wordsDict.length;int ans len;if(word1.equals(word2)){int prev -1;for(int i 0;i<len;i){String word wordsDict[i];if(word.equa…...

数字化时代的智能支持:亚马逊云科技轻量应用服务器技术领先

轻量应用服务器是一种简化运维、门槛低的弹性服务器&#xff0c;它的"轻"主要体现在几个方面&#xff1a;开箱即用、应用优质、上手简洁、投入划算、运维简便以及稳定可靠。相较于普通的云服务器&#xff0c;轻量应用服务器简化了云服务的操作难度、使用和管理流程&a…...

【智慧之窗】AI驱动产品探索

一.初识 ChatGPT ChatGPT 是由 OpenAI 开发的自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;基于 GPT&#xff08;Generative Pre-trained Transformer&#xff09;架构。GPT 系列的模型旨在理解和生成自然语言文本。ChatGPT 专注于支持对话性任务&#xff0c;即与…...

BBS项目--登录

BBS阶段性测试总要求 django登录报错 Error: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。 原因分析&#xff1a;出现这种情况在Windows中很常见&#xff0c;就是端口被占用 解决措施&#xff1a;这时我们只需改一下端口便可以了 登录前端页面(HTML…...

Python---TCP服务端程序开发

1. 开发 TCP 服务端程序开发步骤回顾 创建服务端端套接字对象绑定端口号设置监听等待接受客户端的连接请求接收数据发送数据关闭套接字 2. socket 类的介绍 导入 socket 模块import socket 创建服务端 socket 对象socket.socket(AddressFamily, Type) 参数说明: AddressF…...

回归预测 | MATLAB实现GWO-DHKELM基于灰狼算法优化深度混合核极限学习机的数据回归预测 (多指标,多图)

回归预测 | MATLAB实现GWO-DHKELM基于灰狼算法优化深度混合核极限学习机的数据回归预测 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现GWO-DHKELM基于灰狼算法优化深度混合核极限学习机的数据回归预测 &#xff08;多指标&#xff0c;多图&#…...

听GPT 讲Rust源代码--src/tools(15)

File: rust/src/tools/rust-analyzer/crates/mbe/src/token_map.rs 在Rust源代码中&#xff0c;rust/src/tools/rust-analyzer/crates/mbe/src/token_map.rs文件的作用是实现了一个能够将输入的文本映射为标记的结构。具体来说&#xff0c;它定义和实现了几个结构体&#xff08…...

python可以做小程序研发嘛,python能做微信小程序吗

大家好&#xff0c;给大家分享一下python可以做微信小程序开发吗&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 大家好&#xff0c;给大家分享一下用python编写一个小程序&#xff0c;很多人还不知道这一点。下面详细解释一下用python代码…...

创建型模式 | 单例模式

一、单例模式 单例模式(Singleton Pattern)&#xff0c;使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例被构造&#xff0c;并提供一个访问它的全局访问接口&#xff0c;该实例被程序的所有模块共享。 1、饿汉式 1.1、基础版本 在程序启动后立刻构造单例&#xff0…...

【无标题】欢迎使用Markdown编辑器

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

Postgresql中PL/pgSQL的游标、自定义函数、存储过程的使用

场景 Postgresql中PL/pgSQL代码块的语法与使用-声明与赋值、IF语句、CASE语句、循环语句&#xff1a; Postgresql中PL/pgSQL代码块的语法与使用-声明与赋值、IF语句、CASE语句、循环语句-CSDN博客 上面讲了基本语法&#xff0c;下面记录游标、自定义函数、存储过程的使用。 …...

【IDEA】Intellij IDEA相关配置

IDEA 全称 IntelliJ IDEA&#xff0c;是java编程语言的集成开发环境。IntelliJ在业界被公认为最好的Java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超…...

GD32移植STM32工程(因为懒,所以移植)

文章目录 一、前言二、差异性三、软件移植部分1.前期准备1.1 安装GD32固件库1.2 选择所用芯片 2.修改程序2.1 启动时间&#xff08;内部时钟可不改&#xff09;2.2 主频2.2.1 系统时钟配置2.2.2 108MHz宏定义第一处第二处第三处第四处第五处 2.2.3 串口2.2.4 FLASH 四、总结 一…...

mt5和mt4交易软件有什么区别?

MetaTrader 4&#xff08;MT4&#xff09;和MetaTrader 5&#xff08;MT5&#xff09;是两种广泛使用的外汇和金融市场交易平台&#xff0c;由MetaQuotes公司开发。尽管它们都是外汇交易的常见选择&#xff0c;但在功能和特性上存在一些区别。以下是MT4和MT5之间的主要区别&…...

零刻EQ12 N100 双2.5G网口 All In One新手教程

零刻EQ12 N100 双2.5G网口 All In One新手教程 前言1.硬件配置2.准备工作2.1. ESXI8.0U2镜像2.2. Rufus磁盘工具下载2.3. ikuai镜像下载2.4. StarWindConverter虚拟磁盘格式转换工具下载2.5. OpenWrt镜像下载2.6. 黑群晖RR引导镜像下载(DSM7.2)2.7. 需要准备的硬件2.8. 格式化需…...

竞赛保研 基于Django与深度学习的股票预测系统

文章目录 0 前言1 课题背景2 实现效果3 Django框架4 数据整理5 模型准备和训练6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于Django与深度学习的股票预测系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff…...

听GPT 讲Rust源代码--src/tools(16)

File: rust/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs rust-analyzer是一个基于Rust语言的IntelliSense引擎&#xff0c;用于提供IDE自动补全、代码导航和其他代码编辑功能。在rust-analyzer的源代码中&#xff0c;rust/src/tools/rust-analyzer…...

Leetcoed 双指针

三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。 请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组…...

关于“Python”的核心知识点整理大全31

目录 12.4.2 在屏幕上绘制飞船 alien_invasion.py ​编辑12.5 重构&#xff1a;模块 game_functions 12.5.1 函数 check_events() game_functions.py alien_invasion.py 12.5.2 函数 update_screen() game_functions.py alien_invasion.py 12.6 驾驶飞船 12.6.1 响应…...

第1章 SpringBoot开发入门

学习目标 了解SpringBoot的优点 掌握SpringBoot项目的构建 掌握SpringBoot的单元测试和热部署 熟悉SpringBoot的自动化配置原理 熟悉SpringBoot的执行流程 随着互联网的兴起&#xff0c;Spring势如破竹地占据了Java领域轻量级开发的王者之位。随着Java语言的发展以及市场…...

利用prometheus+grafana进行Linux主机监控

文章目录 一.架构说明与资源准备二.部署prometheus1.上传软件包2.解压软件包并移动到指定位置3.修改配置文件4.编写启动脚本5.启动prometheus服务 三.部署node-exporter1.上传和解压软件包2.设置systemctl启动3.启动服务 四.部署grafana1.安装和启动grafana2.设置prometheus数据…...

单词反转(字符串)

题目名字 单词反转 题目链接 题意 输入倒序的字符串&#xff0c;要求输出正序的字符串 思路 用while输入&#xff0c;这样当出现输入是空格时自动划分上一个为一个单词然后再次反输出 while循环的条件是当不再输入的时候&#xff0c;因为是字符串&#xff0c;不用getline输入…...