HarmonyOS 数据管理与应用数据持久化(二)

news2024/11/26 20:30:30

通过键值型数据库实现数据持久化

场景介绍

键值型数据库存储键值对形式的数据,当需要存储的数据没有复杂的关系模型,比如存储商品名称及对应价格、员工工号及今日是否已出勤等,由于数据复杂度低,更容易兼容不同数据库版本和设备类型,因此推荐使用键值型数据库持久化此类数据。

约束限制

● 设备协同数据库,针对每条记录,Key 的长度≤896 Byte,Value 的长度<4 MB。

● 单版本数据库,针对每条记录,Key 的长度≤1 KB,Value 的长度<4 MB。

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

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

接口说明

以下是键值型数据库持久化功能的相关接口,大部分为异步接口。异步接口均有 callback 和 Promise 两种返回形式,下表均以 callback 形式为例,更多接口及使用方式请见分布式键值数据库。

开发步骤

1.  若要使用键值型数据库,首先要获取一个 KVManager 实例,用于管理数据库对象。示例代码如下所示:Stage 模型示例:

// 导入模块import distributedKVStore from '@ohos.data.distributedKVStore';
// Stage模型import UIAbility from '@ohos.app.ability.UIAbility';
let kvManager;
export default class EntryAbility extends UIAbility {  onCreate() {    let context = this.context;    const kvManagerConfig = {      context: context,      bundleName: 'com.example.datamanagertest'    };    try {      // 创建KVManager实例      kvManager = distributedKVStore.createKVManager(kvManagerConfig);      console.info('Succeeded in creating KVManager.');      // 继续创建获取数据库    } catch (e) {      console.error(`Failed to create KVManager. Code:${e.code},message:${e.message}`);    }  }}

FA 模型示例:

// 导入模块import distributedKVStore from '@ohos.data.distributedKVStore';
// FA模型import featureAbility from '@ohos.ability.featureAbility';
let kvManager;let context = featureAbility.getContext(); // 获取contextconst kvManagerConfig = {  context: context,  bundleName: 'com.example.datamanagertest'};try {  kvManager = distributedKVStore.createKVManager(kvManagerConfig);  console.info('Succeeded in creating KVManager.');  // 继续创建获取数据库} catch (e) {  console.error(`Failed to create KVManager. Code:${e.code},message:${e.message}`);}

2.  创建并获取键值数据库。示例代码如下所示:

try {  const options = {    createIfMissing: true, // 当数据库文件不存在时是否创建数据库,默认创建    encrypt: false, // 设置数据库文件是否加密,默认不加密     backup: false, // 设置数据库文件是否备份,默认备份    kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION, // 设置要创建的数据库类型,默认为多设备协同数据库    securityLevel: distributedKVStore.SecurityLevel.S2 // 设置数据库安全级别  };  // storeId为数据库唯一标识符  kvManager.getKVStore('storeId', options, (err, kvStore) => {    if (err) {      console.error(`Failed to get KVStore. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in getting KVStore.');    // 进行相关数据操作  });} catch (e) {  console.error(`An unexpected error occurred. Code:${e.code},message:${e.message}`);}

3.  调用 put()方法向键值数据库中插入数据。示例代码如下所示:

const KEY_TEST_STRING_ELEMENT = 'key_test_string';const VALUE_TEST_STRING_ELEMENT = 'value_test_string';try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (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}`);}

说明

当 Key 值存在时,put()方法会修改其值,否则新增一条数据。

4.  调用 get()方法获取指定键的值。示例代码如下所示:

const KEY_TEST_STRING_ELEMENT = 'key_test_string';const VALUE_TEST_STRING_ELEMENT = 'value_test_string';try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {    if (err !== undefined) {      console.error(`Failed to put data. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in putting data.');    kvStore.get(KEY_TEST_STRING_ELEMENT, (err, data) => {      if (err !== undefined) {        console.error(`Failed to get data. Code:${err.code},message:${err.message}`);        return;      }      console.info(`Succeeded in getting data. data:${data}`);    });  });} catch (e) {  console.error(`Failed to get data. Code:${e.code},message:${e.message}`);}

5.  调用 delete()方法删除指定键值的数据。示例代码如下所示:

const KEY_TEST_STRING_ELEMENT = 'key_test_string';const VALUE_TEST_STRING_ELEMENT = 'value_test_string';try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {    if (err !== undefined) {      console.error(`Failed to put data. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in putting data.');    kvStore.delete(KEY_TEST_STRING_ELEMENT, (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}`);}

通过关系型数据库实现数据持久化

场景介绍

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

基本概念

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

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

运作机制

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

图 1 关系型数据库运作机制

约束限制

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

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

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

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

接口说明

以下是关系型数据库持久化功能的相关接口,大部分为异步接口。异步接口均有 callback 和 Promise 两种返回形式,下表均以 callback 形式为例,更多接口及使用方式请见关系型数据库。

开发步骤

1.  使用关系型数据库实现数据持久化,需要获取一个 RdbStore。示例代码如下所示:Stage 模型示例:

import relationalStore from '@ohos.data.relationalStore'; // 导入模块 import UIAbility from '@ohos.app.ability.UIAbility';
class EntryAbility extends UIAbility {  onWindowStageCreate(windowStage) {    const STORE_CONFIG = {      name: 'RdbTest.db', // 数据库文件名      securityLevel: relationalStore.SecurityLevel.S1 // 数据库安全级别    };
    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)'; // 建表Sql语句
    relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => {      if (err) {        console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);        return;      }      console.info(`Succeeded in getting RdbStore.`);      store.executeSql(SQL_CREATE_TABLE); // 创建数据表
      // 这里执行数据库的增、删、改、查等操作
    });  }}

FA 模型示例:

import relationalStore from '@ohos.data.relationalStore'; // 导入模块import featureAbility from '@ohos.ability.featureAbility';
// 获取contextlet context = featureAbility.getContext();
const STORE_CONFIG = {  name: 'RdbTest.db', // 数据库文件名  securityLevel: relationalStore.SecurityLevel.S1 // 数据库安全级别};
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)'; // 建表Sql语句
relationalStore.getRdbStore(context, STORE_CONFIG, (err, store) => {  if (err) {    console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);    return;  }  console.info(`Succeeded in getting RdbStore.`);  store.executeSql(SQL_CREATE_TABLE); // 创建数据表
  // 这里执行数据库的增、删、改、查等操作
});

说明

● 应用创建的数据库与其上下文(Context)有关,即使使用同样的数据库名称,但不同的应用上下文,会产生多个数据库,例如每个 UIAbility 都有各自的上下文。

● 当应用首次获取数据库(调用 getRdbStore)后,在应用沙箱内会产生对应的数据库文件。使用数据库的过程中,在与数据库文件相同的目录下可能会产生以-wal 和-shm 结尾的临时文件。此时若开发者希望移动数据库文件到其它地方使用查看,则需要同时移动这些临时文件,当应用被卸载完成后,其在设备上产生的数据库文件及临时文件也会被移除。

2.  获取到 RdbStore 后,调用 insert()接口插入数据。示例代码如下所示:

const valueBucket = {  'NAME': 'Lisa',  'AGE': 18,  'SALARY': 100.5,  'CODES': new Uint8Array([1, 2, 3, 4, 5])};store.insert('EMPLOYEE', valueBucket, (err, rowId) => {  if (err) {    console.error(`Failed to insert data. Code:${err.code}, message:${err.message}`);    return;  }  console.info(`Succeeded in inserting data. rowId:${rowId}`);})

说明

关系型数据库没有显式的 flush 操作实现持久化,数据插入即保存在持久化文件。

3.  根据谓词指定的实例对象,对数据进行修改或删除。调用 update()方法修改数据,调用 delete()方法删除数据。示例代码如下所示:

// 修改数据const valueBucket = {  'NAME': 'Rose',  'AGE': 22,  'SALARY': 200.5,  'CODES': new Uint8Array([1, 2, 3, 4, 5])};let predicates = new relationalStore.RdbPredicates('EMPLOYEE'); // 创建表'EMPLOYEE'的predicatespredicates.equalTo('NAME', 'Lisa'); // 匹配表'EMPLOYEE'中'NAME'为'Lisa'的字段store.update(valueBucket, predicates, (err, rows) => {  if (err) {    console.error(`Failed to update data. Code:${err.code}, message:${err.message}`);    return;  }  console.info(`Succeeded in updating data. row count: ${rows}`);})
// 删除数据let predicates = new relationalStore.RdbPredicates('EMPLOYEE');predicates.equalTo('NAME', 'Lisa');store.delete(predicates, (err, rows) => {  if (err) {    console.error(`Failed to delete data. Code:${err.code}, message:${err.message}`);    return;  }  console.info(`Delete rows: ${rows}`);})

4.  根据谓词指定的查询条件查找数据。调用 query()方法查找数据,返回一个 ResultSet 结果集。示例代码如下所示:

let predicates = new relationalStore.RdbPredicates('EMPLOYEE');predicates.equalTo('NAME', 'Rose');store.query(predicates, ['ID', 'NAME', 'AGE', 'SALARY', 'CODES'], (err, resultSet) => {  if (err) {    console.error(`Failed to query data. Code:${err.code}, message:${err.message}`);    return;  }  console.info(`ResultSet column names: ${resultSet.columnNames}`);  console.info(`ResultSet column count: ${resultSet.columnCount}`);})

说明

当应用完成查询数据操作,不再使用结果集(ResultSet)时,请及时调用 close 方法关闭结果集,释放系统为其分配的内存。

5.  删除数据库。调用 deleteRdbStore()方法,删除数据库及数据库相关文件。示例代码如下:

Stage 模型示例:

import UIAbility from '@ohos.app.ability.UIAbility';
class EntryAbility extends UIAbility {  onWindowStageCreate(windowStage) {    relationalStore.deleteRdbStore(this.context, 'RdbTest.db', (err) => {      if (err) {        console.error(`Failed to delete RdbStore. Code:${err.code}, message:${err.message}`);        return;      }      console.info('Succeeded in deleting RdbStore.');    });  }}

FA 模型示例:

import featureAbility from '@ohos.ability.featureAbility';
// 获取contextlet context = featureAbility.getContext();
relationalStore.deleteRdbStore(context, 'RdbTest.db', (err) => {  if (err) {    console.error(`Failed to delete RdbStore. Code:${err.code}, message:${err.message}`);    return;  }  console.info('Succeeded in deleting RdbStore.');});

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FreeRTOS_软件定时器

目录 1. 软件定时器简介 2. 定时器服务/Daemon 任务 2.1 定时器服务任务与队列 2.2 定时器相关配置 2.2.1 configUSE_TIMERS 2.2.2 configTIMER_TASK_PRIORITY 2.2.3 configTIMER_QUEUE_LENGTH 2.2.4 configTIMER_TASK_STACK_DEPTH 2.3 单次定时器和周期定时器 2.4 复…

在公共安全场景下,智能监控如何做到保障安全的同时又最大化地提供便利?

智能监控系统应用的场景十分广泛&#xff0c;其中&#xff0c;公共安全场所的需求尤为重要&#xff0c;为保障公共区域的安全&#xff0c;提升人民群众的归属感&#xff0c;增强公共场所的安全性&#xff0c;智慧安防EasyCVR智能视频监控系统做出了极大努力。具体细节如下&…

33 mysql find_in_set 的实现

前言 这里我们主要是来探讨一下 mysql 中 in 的使用, find_in_set 的使用 这两者 在我们实际应用中应该也是 非常常用的了 测试数据表如下 CREATE TABLE tz_test (id int(11) unsigned NOT NULL AUTO_INCREMENT,field1 varchar(16) DEFAULT NULL,field2 varchar(16) DEFAU…

MobPush智能推送:数智化运营加速用户转化

随着移动应用市场竞争日益激烈&#xff0c;如何保持APP用户活跃度实现商业价值成为无数APP运营者的烦恼。是继续加大力度拉新促活&#xff0c;用庞大的用户体量获得平台商业价值&#xff1f;还是加强对存量用户的精细化运营&#xff0c;激发存量用户付费转化实现弯道超车&#…

python爬虫实战——今日头条新闻数据获取

大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 第三方库: requests >>> pip install requests 第三方模块安装&#xff1a; win R 输入cmd 输入安装命令 pip install 模块名 (如果你觉得安装速度比较慢, 你…

【前端周报11.03】

前端周汇报11.03 那我们接着上一周的继续往下进行推进上周总结本周工作下周内容 那我们接着上一周的继续往下进行推进 上周总结 上一周的话我其实最主要的工作还是进行了一系列的调研主要的话是针对于我们未来要做的小程序的项目的&#xff0c;为未来开发这个小程序做好一系列…

一整套智慧工地源码,劳务实名制、施工安全管理、绿色施工、危大工程设备监测、视频AI识别功能

智慧工地系统充分利用计算机技术、互联网、物联网、云计算、大数据等新一代信息技术&#xff0c;以PC端&#xff0c;移动端&#xff0c;设备端三位一体的管控方式为企业现场工程管理提供了先进的技术手段。让劳务、设备、物料、安全、环境、能源、资料、计划、质量、视频监控等…

c 函数调用过程中,调用函数的栈帧一旦被修改,被调用函数则无法正确返回。( X )

当一个函数被调用时&#xff0c;它的栈帧会被创建并压入调用栈中。栈帧包含了函数的局部变量、参数以及返回地址等信息。当函数执行完毕后&#xff0c;栈帧会被弹出&#xff0c;返回到调用函数的位置继续执行。 下面是一个示例代码&#xff0c;展示了调用函数栈帧被修改但不影…

【Python_GraphicsView 学习笔记(一)】Graphics View框架的基本介绍

【Python_GraphicsView 学习笔记&#xff08;一&#xff09;】Graphics View框架的基本介绍 前言正文1、Graphics View框架简介2、Graphics View框架与QPainter类的区别3、Graphics View框架的三个组成部分4、场景QGraphicsScene类5、视图QGraphicsView类6、图形项QGraphicsIte…

解析电源模块功能测试项目 电源模块测试系统助力功能测试

电源测试一般包括保护特性测试、安规测试、电磁兼容测试、可靠性测试、功能测试以及其它一些特定测试。电源功能测试是评估电源质量好坏、性能、响应等的重要测试方法&#xff0c;也是电源的常规测试内容。 电源功能测试项目 电源功能测试是确保电源稳定性和可靠性的重要测试指…

使用android studio开发flutter应用,10分钟环境配置

1.安装flutter sdk 安装中文官网配置环境即可&#xff1a;安装和环境配置 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 然后如果你的网络不好的话&#xff0c;可以修改flutter的源地址&#xff0c;将下面的变量创建成新的环境变量 FLUTTER_STORAGE_BASE_URLhttp…

接口测试框架中的鉴权处理!

接口自动化测试中通常都有鉴权机制&#xff0c;就是判断是否在登录状态下&#xff0c;已登录方可调用接口&#xff0c;未登录则不可调用。本文将带领大家学习使用rest-assured框架实现基于cookies和token的鉴权关联&#xff0c;实现接口自动化测试。 1、基于cookies的鉴权关联…

创建自定义美颜滤镜:使用第三方美颜SDK的步骤指南

美颜滤镜在现代移动应用和直播平台中变得越来越受欢迎。它们可以让用户在自拍照片、视频聊天或实时直播中看起来更加美丽和自信。如果您是一位应用开发者&#xff0c;想要增加美颜滤镜功能&#xff0c;但又不想从头开始构建整个系统&#xff0c;那么使用第三方美颜SDK可能是一个…

【C++ 学习 ㉚】- 超详解 C++11 的右值引用

目录 一、左值和右值 二、左值引用和右值引用 三、移动语义 3.1 - 左值引用的短板 3.2 - 移动构造和移动赋值 四、move 函数 4.1 - remove_reference 的实现 4.2 - move 的实现 五、完美转发 5.1 - forward 的实现 5.2 - 使用场景 很多初学者都感觉右值引用晦涩难懂…

宽以光电厚以激光 组合式测宽测厚仪 性价比更高

对于板材类产品而言&#xff0c;对其几何尺寸的品质检测&#xff0c;往往是宽度与厚度兼具的&#xff0c;为了同时满足两种检测需求&#xff0c;制造了组合式测宽测厚仪。 单独的测宽仪的原理有光电、机器视觉、激光等&#xff0c;光电测宽仪不仅可选择的测量原理多&#xff0c…

若依分离版——配置多数据源(mysql和oracle),实现一个方法操作多个数据源

目录 一、若依平台配置 二、编写oracle数据库访问的各类文件 三. 一个方法操作多个数据源 一、若依平台配置 1、在ruoyi-admin的pom.xml添加依赖 <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version…

tensorflow-gpu 找不到指定模块

排除&#xff1a; 1.python编译器是64位 查询教程 2. cuda cudnn版本 均是12.2 可以向下兼容 cmd&#xff1a; nvcc -V即可 另一种方法 tensorflow官网教程 pip install tensorflow_gpu1.12.0 4.安装torch-gpu 检查所在环境 解决&#xff01;&#xff01; conda install …

瑞禧生物分享~今天是 碲化银粉体 Ag2Te CAS:12002-99-2

碲化银粉体 Ag2Te CAS&#xff1a;12002-99-2 纯度&#xff1a;99% 仅用于科研 储藏条件&#xff1a;冷藏-20℃ 简介&#xff1a;碲化银是一种无机化合物&#xff0c;化学式是Ag2Te。它是一种单斜晶体&#xff0c;并以矿物的形式存在于自然界中。化学计量的碲化银具有n型半导…

生成第一个 Blazor 应用

前言&#xff1a;博主文章仅用于学习、研究和交流目的&#xff0c;不足和错误之处在所难免&#xff0c;希望大家能够批评指出&#xff0c;博主核实后马上更改。 概述&#xff1a;Blazor 是一个使用 Blazor 生成交互式客户端 Web UI 的框架使用 C# 创建丰富的交互式 UI。共享使…

rabbitmq的confirm模式获取correlationData为null解决办法

回调函数confirm中的correlationDatanull // 实现confirm回调,发送到和没发送到exchange,都触发 Override public void confirm(CorrelationData correlationData, boolean ack, String cause) {// 参数说明:// correlationData: 相关数据,可以在发送消息时,进行设置该参数// …