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…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...