HarmonyOS之sqlite数据库的使用
从API Version 9开始,鸿蒙开发中sqlite使用新接口@ohos.data.relationalStore
但是 relationalStore在 getRdbStore操作时,在预览模式运行或者远程模拟器运行都会报错,导致无法使用。查了一圈说只有在真机上可以正常使用,因此这里暂且使用 @ohos.data.rdb
二者的接口非常相似,会使用了ohos.data.rdb,自然也会使用ohos.data.relationalStore
在harmonyos开发中,操作数据库时,我们通常习惯将一个功能模块数据库操作全部写在一个ets文件中并export,在界面文件中直接导入使用。
1.数据库配置以及建表
新建userDb.ets文件并添加以下代码
import data_rdb from '@ohos.data.rdb'
const STORE_CONFIG = {name: "test.db"}
const TAB_USER = "user"
const CREATE_TABLE_CODE = "CREATE TABLE IF NOT EXISTS "+TAB_USER+" ("+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "+ "name TEXT , "+ "age TEXT , "+ "sex TEXT ) "
export function createTable(context) {data_rdb.getRdbStore(context,STORE_CONFIG, 1, function (err, rdbStore) {rdbStore.executeSql(CREATE_TABLE_CODE)console.info('create table done.')})
}
在User.ets界面导入并调用
import {createTable} from '../utils/userDb'aboutToAppear() {createTable(getContext(this))
}
2.插入数据
userDb.ets文件添加 insertData方法,这里需要注意的是promise的用法,因为需要将执行结果返回界面,所以方法里面多次使用了Promise来返回结果
插入的字段要和数据库字段保持一致。
export function insertData(context,list):any{const promise = data_rdb.getRdbStore(context,STORE_CONFIG, 1)return promise.then(async (rdbStore) => {let arr:any = [];for(let i:number=0; i<list.length; i++){const obj = list[i]const item ={name: obj.name,age: obj.age,sex: obj.sex}rdbStore.insert(TAB_USER, item);}console.log('--start')console.log('完了')return true;})
}
在User.ets界面导入并调用
import {insertData} from '../utils/userDb'addData(){let array = [];for(let i=0; i<20; i++){array.push({name:'张飞'+i,age: 20+i,sex: '男'})}insertData(getContext(this), array).then(res=>{if(res){this.loading = falsethis.showDialog('添加成功')this.search(true)}})}
3.查询
userDb.ets文件添加 queryDataPage方法,这里用了分页查询的方式,还有一种谓词的查询方式请参考官方文档。
export function queryDataPage(context,param):any {let promise = data_rdb.getRdbStore(context, STORE_CONFIG, 1)return promise.then(async (rdbStore) => {const sql: string = "select * from "+TAB_USER+" where name like ? " +"order by id asc limit ? OFFSET ? ";console.log('----sql---', sql)const pS = param.pageSizeconst page = param.pageconsole.log('param.code', param.code)console.log('pS', pS)console.log('(page-1)*pS', (page - 1) * pS)// param.code,pS,(page-1)*pS]let promisequery = rdbStore.querySql(sql, [param.code, pS, (page - 1) * pS])return promisequery.then(async (resultSet) => {const rowCount = resultSet.rowCount;let list = [];console.log("rowCount --" + rowCount)resultSet.goToFirstRow();for (let i = 0; i < rowCount; i++) {const name = resultSet.getString(resultSet.getColumnIndex("NAME"))const age = resultSet.getString(resultSet.getColumnIndex("AGE"))const sex = resultSet.getString(resultSet.getColumnIndex("SEX"))const id = resultSet.getString(resultSet.getColumnIndex("ID"))resultSet.goToNextRow();const data = {name,id,age,sex,}list.push(data);}resultSet.close();console.log('--array--', list.length)return list;})}).catch((err) => {console.log("Get RdbStore failed, err: " + err)})
}
在User.ets界面导入并调用
import {queryDataPage} from '../utils/userDb'@State list:Array<any> = []@State keyword:string = ""@State page:number = 1@State pageSize:number = 20
search(firstPage:boolean){if(firstPage){this.page = 1}const params = {code: '%'+this.keyword+'%',page: this.page,pageSize: this.pageSize,}queryDataPage(getContext(this), params).then(data=>{if(data){console.log('res',JSON.stringify(data));if(this.page == 1){this.list = data} else {this.list = this.list.concat(data);}}})}
4.更新数据
userDb.ets文件添加 updateData方法
export function updateData(context,newInfo):any{const promise = data_rdb.getRdbStore(context,STORE_CONFIG, 1)return promise.then(async (rdbStore) => {let predicates = new data_rdb.RdbPredicates(TAB_USER);predicates.equalTo("id", newInfo.id)let promiseUp = rdbStore.update(newInfo, predicates)return promiseUp.then(async (rows) => {if(rows == 1){return true}}).catch((err) => {console.info("Updated failed, err: " + err)return false})})
}
在User.ets界面导入并调用
import {updateData} from '../utils/userDb'updateOne(item:any){item.name = '张飞111'updateData(getContext(this), item).then(res=>{if(res){this.showDialog('更新成功')this.search(true)}})}
5.删除数据
userDb.ets文件添加 deleteOneData方法
export function deteteOneData(context,id):any{const promise = data_rdb.getRdbStore(context,STORE_CONFIG, 1)return promise.then(async (rdbStore) => {let predicates = new data_rdb.RdbPredicates(TAB_USER);predicates.equalTo("id", id)const result = rdbStore.delete(predicates);console.log('--result--'+JSON.stringify(result))return true;})
}
在User.ets界面导入并调用
import {deteteOneData} from '../utils/userDb'deleteOne(id:string){deteteOneData(getContext(this), id).then(res=>{if(res){this.showDialog('删除成功')this.search(true)}})}
6.界面效果
点击右上角Add按钮,插入数据;
点击删除按钮,删除一条数据;
点击编辑按钮,将该条数据姓名字段更新为 马超000。

7.完整代码
界面文件 User.ets
import {createTable,insertData,deteteOneData,updateData,queryDataPage} from '../utils/userDb'
@Entry
@Component
struct User {controller: SearchController = new SearchController()@State codeList:Array<any> = [];@State list:Array<any> = [];@State loading:boolean = false;@State keyword:string = "";@State page:number = 1;@State pageSize:number = 20;aboutToAppear() {createTable(getContext(this))}onReachEnd(){console.log('--------onReachEnd---');//this.page = this.page+1this.search(false)}search(firstPage:boolean){if(firstPage){this.page = 1}const params = {code: '%'+this.keyword+'%',page: this.page,pageSize: this.pageSize,}queryDataPage(getContext(this), params).then(data=>{if(data){console.log('res',JSON.stringify(data));if(this.page == 1){this.list = data} else {this.list = this.list.concat(data);}}})}addData(){let array = [];for(let i=0; i<20; i++){array.push({name:'张飞'+i,age: 20+i,sex: '男'})}insertData(getContext(this), array).then(res=>{if(res){this.loading = falsethis.showDialog('添加成功')this.search(true)}})}deleteOne(id:string){deteteOneData(getContext(this), id).then(res=>{if(res){this.showDialog('删除成功')this.search(true)}})}updateOne(item:any){item.name = '马超000'updateData(getContext(this), item).then(res=>{if(res){this.showDialog('更新成功')this.search(true)}})}showDialog(text:string){AlertDialog.show({title: '提示',message: text,autoCancel: true,alignment: DialogAlignment.Center,gridCount: 4,offset: { dx: 0, dy: -20 },primaryButton: {value: '确定',action: () => {console.info('Callback when the first button is clicked')}},})}toAddData(){AlertDialog.show({title: '提示',message: '确定要添加数据吗',autoCancel: true,alignment: DialogAlignment.Center,offset: { dx: 0, dy: -20 },gridCount: 5,primaryButton: {value: '确定',action: () => {console.info('确定 is clicked')this.loading = truethis.addData()}},secondaryButton: {value: '取消',action: () => {console.info('取消 is clicked')}},cancel: () => {console.info('Closed callbacks')}})}@Builder NavigationMenus() {Row() {Text("Add").width(32).height(28).onClick(()=>this.toAddData())}}@Builder buildList(){Row(){Text('姓名')Text('年龄')Text('性别')Text('操作')}.justifyContent(FlexAlign.SpaceAround).width('100%').padding({top:5,bottom: 10})List({ space: 20, initialIndex: 0 }) {ForEach(this.list, (item) => {ListItem() {Row(){Text(item.name)Text(item.age)Text(item.sex)Row(){Text('删除').onClick(()=>{this.deleteOne(item.id)}).fontColor(Color.Red).margin({right:5})Text('编辑').onClick(()=>{this.updateOne(item)}).fontColor(Color.Blue)}}.justifyContent(FlexAlign.SpaceAround).width('100%')}.editable(true)}, item => item.name)}.onScrollIndex((firstIndex: number, lastIndex: number) => {//console.info('first' + firstIndex)//console.info('last' + lastIndex)}).onReachEnd(()=>{this.onReachEnd()}).listDirection(Axis.Vertical) // 排列方向.divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线.edgeEffect(EdgeEffect.None) // 滑动到边缘无效果.chainAnimation(false) // 联动特效关闭.width('100%')}@Builder buildSearch(){Search({ value: this.keyword, placeholder: '请输入姓名...', controller: this.controller }).searchButton('搜索').width('100%').height(40).backgroundColor('#F5F5F5').placeholderColor(Color.Grey).placeholderFont({ size: 14, weight: 400 }).textFont({ size: 14, weight: 400 }).onSubmit((value: string) => {console.log('---999')//this.submitValue = valuethis.keyword = valuethis.search(true)}).onChange((value: string) => {this.keyword = value})}build() {Column(){Navigation() {Column(){this.buildSearch()if(this.loading){Column(){LoadingProgress().color(Color.Blue)}.width('40%').height('40%')}this.buildList()}.height('100%')}.title("用户管理").menus(this.NavigationMenus).titleMode(NavigationTitleMode.Mini)}.height('100%')}
}
数据操作文件 userDb.ets
import data_rdb from '@ohos.data.rdb'
const STORE_CONFIG = {name: "test.db"}
const TAB_USER = "user"
const CREATE_TABLE_CODE = "CREATE TABLE IF NOT EXISTS "+TAB_USER+" ("+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "+ "name TEXT , "+ "age TEXT , "+ "sex TEXT ) "
export function createTable(context) {data_rdb.getRdbStore(context,STORE_CONFIG, 1, function (err, rdbStore) {rdbStore.executeSql(CREATE_TABLE_CODE)console.info('create table done.')})
}
export function updateData(context,newInfo):any{const promise = data_rdb.getRdbStore(context,STORE_CONFIG, 1)return promise.then(async (rdbStore) => {let predicates = new data_rdb.RdbPredicates(TAB_USER);predicates.equalTo("id", newInfo.id)let promiseUp = rdbStore.update(newInfo, predicates)return promiseUp.then(async (rows) => {if(rows == 1){return true}}).catch((err) => {console.info("Updated failed, err: " + err)return false})})
}
export function insertData(context,list):any{const promise = data_rdb.getRdbStore(context,STORE_CONFIG, 1)return promise.then(async (rdbStore) => {let arr:any = [];for(let i:number=0; i<list.length; i++){const obj = list[i]const item ={name: obj.name,age: obj.age,sex: obj.sex}rdbStore.insert(TAB_USER, item);}console.log('--start')console.log('完了')return true;})
}
export function deteteOneData(context,id):any{const promise = data_rdb.getRdbStore(context,STORE_CONFIG, 1)return promise.then(async (rdbStore) => {let predicates = new data_rdb.RdbPredicates(TAB_USER);predicates.equalTo("id", id)const result = rdbStore.delete(predicates);console.log('--result--'+JSON.stringify(result))return true;})
}
export function detelteAllCode(context){data_rdb.getRdbStore(context,STORE_CONFIG, 1, function (err, rdbStore) {rdbStore.executeSql("delete from "+TAB_USER)console.info('--delete code done.')})}
export function queryDataPage(context,param):any {let promise = data_rdb.getRdbStore(context, STORE_CONFIG, 1)return promise.then(async (rdbStore) => {const sql: string = "select * from "+TAB_USER+" where name like ? " +"order by id asc limit ? OFFSET ? ";console.log('----sql---', sql)const pS = param.pageSizeconst page = param.pageconsole.log('param.code', param.code)console.log('pS', pS)console.log('(page-1)*pS', (page - 1) * pS)// param.code,pS,(page-1)*pS]let promisequery = rdbStore.querySql(sql, [param.code, pS, (page - 1) * pS])return promisequery.then(async (resultSet) => {const rowCount = resultSet.rowCount;let list = [];console.log("rowCount --" + rowCount)resultSet.goToFirstRow();for (let i = 0; i < rowCount; i++) {const name = resultSet.getString(resultSet.getColumnIndex("NAME"))const age = resultSet.getString(resultSet.getColumnIndex("AGE"))const sex = resultSet.getString(resultSet.getColumnIndex("SEX"))const id = resultSet.getString(resultSet.getColumnIndex("ID"))resultSet.goToNextRow();const data = {name,id,age,sex,}list.push(data);}resultSet.close();console.log('--array--', list.length)return list;})}).catch((err) => {console.log("Get RdbStore failed, err: " + err)})
}
相关文章:
HarmonyOS之sqlite数据库的使用
从API Version 9开始,鸿蒙开发中sqlite使用新接口ohos.data.relationalStore 但是 relationalStore在 getRdbStore操作时,在预览模式运行或者远程模拟器运行都会报错,导致无法使用。查了一圈说只有在真机上可以正常使用,因此这里…...
网络抓包命令tcpdump
网络抓包命令tcpdump "tcpdump -i any -nn -vv tcp port 9095 -s 0 -w dump.cap"命令是一个网络抓包命令,用于捕获流经指定网络接口的TCP协议、端口号为9095的网络数据包,并将这些数据包写入到名为"dump.cap"的文件中。 具体参数解…...
iTMSTransporter上传ipa文件
背景 uni-app云打包之后生成的ipa包需要上传到app store上,applicationloader和香蕉云编都收费,转用iTMSTransporter上传 环境:mac 第1步 选择安装目录 xcode-select --switch /Applications/Xcode.app/Contents/Developer第2步 下载 xcru…...
2024华数杯国际数学建模A题思路模型详解
2024华数杯国际数学建模A题思路论文:1.17上午第一时间持续更新,详细内容见文末名片 建立一个模型来描述放射性废水在海水中的扩散速率和方向,考虑到涉及的物理过程和环境因素的复杂性,我们通常会使用一个简化的扩散模型作为起点…...
JS-定时器-间歇函数(一)
• 定时器函数介绍 定时器函数在开发中的使用场景 网页中经常会需要一种功能:每隔一段时间需要自动执行一段代码,不需要我们手动去触发例如:网页中的倒计时要实现这种需求,需要定时器函数定时器函数有两种,今天我先讲…...
AttributeError: module ‘openai‘ has no attribute ‘error‘解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
每日一记:一个windows的bat脚本工具集
最近在工作上遇到要校验文件的问题,例如,下载了一个文件之后,通过查看文件的md5来校验文件是否完整,这个动作在linux上很简单,但在windows上也不难,可以通过 certutil 命令实现,该命令通常可用于…...
Apache Zeppelin学习记录2
Apache Zeppelin学习记录2 文章目录 Apache Zeppelin学习记录2前言一、基础调用二、带参数调用1.代码块要增加一行z.textbox("folder_path", "input")2.读取result 总结 前言 上一章讲了如何使用zeppelin来接入python,本节我们来看看如何使用R…...
[原创][R语言]股票分析实战[11]:读取股票数据文件的细节: 提取目标列数据
[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…...
【kafka】记录用-----------1
主题(topic):消息的第一次分类 根据人为的划分条件将消息分成不同的主题 主题的划分是人为的根据不同的任务情景去划分 比如,我们有两个主题,一个是"订单",另一个是"库存"。每个主题代…...
uniapp 实现tabBar-switchTab之间的传参
一、需求: tabbar之间跳转页面时,需要传递一个参数。 官方文档明确说明: 跳转tabBar栏的页面只能使用 uni.switchTab 并且url 路径后面不能传递参数。 二、解决方法: 方法1:setStorageSync(本地缓存) //index.vue 页 onclick …...
geemap学习笔记049:下载Landsat数据时遇到的一个问题
前言 最近在下载Landsat 8 地面反射率数据(Surface Reflectance)时,遇到了一个问题,无论是使用geemap.ee_export_image_to_drive() 函数还是geemap.download_ee_image() 函数下载的数据,易康都打不开,显示…...
基于pyqt5+scapy 根据ip 具体端口 进行扫描 的程序
先给出代码 import sysfrom PyQt5 import uic from PyQt5.QtWidgets import *from scapy.all import * import argparse import logging from scapy.layers.inet import IP, TCP from scapy.sendrecv import sr1class MyWindow(QWidget):def __init__(self):super().__init__(…...
Redis:原理速成+项目实战——Redis企业级项目实战终结篇(HyperLogLog实现UV统计)
👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理速成项目实战——Redis实战14(BitMap实现用户签到功能) 📚订阅专栏&am…...
Python的集合set用法介绍与例子
用法简介 Python的集合(set)是一种无序且不重复的元素序列。它类似于列表和元组,但集合中的元素是唯一的,没有重复的值。集合在Python中用于执行一些特定的操作,例如消除重复元素、检查元素是否存在等。 下面是一些关…...
服务器感染了.pings勒索病毒,如何确保数据文件完整恢复?
导言: 随着科技的不断进步,网络犯罪也在不断演变。其中之一的.pings勒索病毒是一种危险的恶意软件,它能够加密用户的数据文件,并要求支付赎金以解密这些文件。在本文中,91数据恢复将介绍.pings勒索病毒,以…...
go语言(二)----常量
1、单个常量用const进行定义。 const a int 100 2、多个常量用const()进行定义。 const ( a 10 b 20 ) 3、iota 与const()来表示枚举类型 const( a iota b c ) package mainimp…...
VSC ctrl+鼠标左键点击后,返回原来位置的方法
windows 在使用VSC编写代码时,我们常常用到Ctrl鼠标左键的方式来查看类或变量名的定义声明,看完之后我们想回到程序原来的位置,此时可以通过Alt ←(方向左键)来返回到原来的位置。...
还在为crontab表达式发愁吗,快使用这个工具
是不是每次要定义cron表达式的时候,都去百度翻找资料,cron表达式难写难记真是苦天下程序员久已。有没有什么不拥记的办法就轻松掌握呢?最近发现这个CrontabGuru神器,强烈推荐,真是广大程序员的福音了。 简介 Crontab…...
61. Spring事务传播行为实现原理
61. Spring事务传播行为实现原理 Spring的事务信息是存在ThreadLocal中的, 所以一个线程永远只能有一个事务 融入:当传播行为是融入外部事务则拿到ThreadLocal中的Connection、共享一个数据库连接共同提交、回滚;创建新事务:当传播行为是创建新事务,会将嵌套新事务存入Th…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
