当前位置: 首页 > 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设计等方面的功能可以说是超…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...