HarmonyOS《柚兔学伴》项目实战19-云数据库——端云数据同步
第19篇云数据库——端云数据同步HarmonyOS 的云数据库Cloud DB提供了端云一致的数据存储方案支持数据在本地和云端之间自动同步实现跨设备数据共享。本篇以柚兔学伴项目为例讲解如何使用kit.CloudFoundationKit中的cloudDatabase模块完成云端数据的查询、插入与更新操作。1. 云数据库基础概念1.1 云数据库 vs 本地 RDB特性云数据库 (Cloud DB)本地 RDB数据存储位置云端 本地缓存仅本地跨设备同步支持不支持网络依赖首次查询需联网无适用场景用户共享数据、跨设备同步离线数据、本地缓存数据类型DatabaseObject 子类ValuesBucket在柚兔学伴中AI 工具卡片Tool、用户单词本Word、长难句Sentence都存储在云数据库中实现不同设备间的学习数据同步。1.2 核心对象关系cloudDatabase.zone(name) → DatabaseZone (数据区域) DatabaseQueryT(Class) → DatabaseQuery (查询条件) DatabaseZone.query(condition) → T[] (查询结果) DatabaseZone.upsert(data) → number (插入/更新)2. 获取 DatabaseZone 实例所有云数据库操作都从获取DatabaseZone开始需要指定区域名称import{cloudDatabase}fromkit.CloudFoundationKit;import{UrlConstants}fromnetwork;agcDataBase:cloudDatabase.DatabaseZonecloudDatabase.zone(UrlConstants.ZONE_NAME);其中ZONE_NAME在UrlConstants中定义为常量exportclassUrlConstants{staticreadonlyZONE_NAME:stringPartner}注意区域名称需与 AGC 控制台中配置的云数据库区域名称一致。3. 定义云对象类型云数据库中的每张表对应一个继承自cloudDatabase.DatabaseObject的类通过naturalbase_ClassName()方法指定表名3.1 ToolAI 工具卡片import{cloudDatabase}fromkit.CloudFoundationKit;classToolextendscloudDatabase.DatabaseObject{id:number|undefined;name:string;cover:string;num:string|undefined;type:string|undefined;naturalbase_ClassName():string{returnTool;}}export{Tool};3.2 Word单词卡片classWordextendscloudDatabase.DatabaseObject{id:number|undefined;name:string|undefined;ttsUrl:string|undefined;pronunciation:string|undefined;means:string|undefined;userId:string|undefined;publicnaturalbase_ClassName():string{returnWord;}}export{Word};3.3 Sentence长难句classSentenceextendscloudDatabase.DatabaseObject{id:number|undefined;src:string|undefined;dst:string|undefined;ttsUrl:string|undefined;userId:string|undefined;publicnaturalbase_ClassName():string{returnSentence;}}export{Sentence};设计要点naturalbase_ClassName()返回的名称必须与 AGC 控制台中定义的表名完全一致字段名与云数据库表中的列名对应userId字段用于实现用户维度的数据隔离4. 查询数据4.1 ChatView查询 Tool 列表在聊天首页加载所有 AI 工具卡片不需要按用户过滤Componentexportstruct ChatView{agcDataBase:cloudDatabase.DatabaseZone|undefinedundefined;condition:cloudDatabase.DatabaseQuerycloudDatabase.DatabaseObject|undefinedundefined;StatecardList:Tool[][]asyncaboutToAppear():Promisevoid{this.agcDataBasecloudDatabase.zone(UrlConstants.ZONE_NAME);this.getCardList()}asyncgetCardList(){letconditionnewcloudDatabase.DatabaseQuery(Tool);try{this.cardListawaitthis.agcDataBase!!.query(condition)hilog.info(0x0000,testTag,Succeeded in querying data, result:${JSON.stringify(this.cardList)});}catch(err){hilog.error(0x0000,testTag,Failed to query data, code:${err.code}, message:${err.message});}}}查询流程new cloudDatabase.DatabaseQuery(Tool)创建以 Tool 类为模板的查询条件不添加任何条件表示查询所有记录agcDataBase.query(condition)执行查询返回Tool[]数组4.2 WordCardPage按用户查询单词单词本需要只显示当前用户的单词通过condition.equalTo(userId, uuid)实现数据隔离Componentstruct WordCardPage{agcDataBase:cloudDatabase.DatabaseZonecloudDatabase.zone(UrlConstants.ZONE_NAME);condition:cloudDatabase.DatabaseQuerycloudDatabase.DatabaseObject|undefinedundefined;StatewordList:Word[][]aboutToAppear():void{this.getWordList().then((wordList:Word[]){this.wordListwordList})}asyncgetWordList():PromiseWord[]{try{this.conditionnewcloudDatabase.DatabaseQuery(Word);letuuidawaitUserInfoManager.getUserInfo()?.unionIDthis.condition.equalTo(userId,uuid)returnawaitthis.agcDataBase?.query(this.condition)asWord[]}catch(err){return[]}}}用户数据隔离的关键步骤通过UserInfoManager.getUserInfo()?.unionID获取用户唯一标识condition.equalTo(userId, uuid)添加等值查询条件查询结果只包含当前用户的单词数据4.3 SentenceCardPage按用户查询长难句查询模式与 WordCardPage 完全一致仅将类型替换为SentenceComponentstruct SentenceCardPage{agcDataBase:cloudDatabase.DatabaseZonecloudDatabase.zone(UrlConstants.ZONE_NAME);condition:cloudDatabase.DatabaseQuerycloudDatabase.DatabaseObject|undefinedundefined;StatesentenceList:Sentence[][]asyncgetWordList():PromiseSentence[]{try{this.conditionnewcloudDatabase.DatabaseQuery(Sentence);letuuidawaitUserInfoManager.getUserInfo()?.unionIDthis.condition.equalTo(userId,uuid)returnawaitthis.agcDataBase?.query(this.condition)asSentence[]}catch(err){return[]}}}5. 插入与更新数据5.1 upsert 操作upsert是云数据库提供的插入或更新操作——如果记录已存在则更新不存在则插入。在ChatView中可以看到注释中的 upsert 用法// 更新卡片点击次数data.num(parseInt(data.num!!)1).toString()this.agcDataBase!!.upsert(data).then((num:number){this.getCardList()}).catch((err:BusinessError){err})5.2 创建新的云对象添加长难句时创建Sentence实例并设置字段值letsentencenewSentence();sentence.srcthis.model.resultData.result!!.trans_result!![0].src sentence.dstthis.model.resultData.result!!.trans_result!![0].dst sentence.ttsUrlthis.model.resultData.result!!.trans_result!![0].dst_tts sentence.userIdUserInfoManager.getUserInfo()?.unionID// this.agcDataBase.upsert(sentence) // 插入到云端步骤new Sentence()创建空的云对象实例设置各字段值特别是userId确保数据归属agcDataBase.upsert(sentence)将数据写入云数据库6. 错误处理云数据库操作涉及网络请求必须做好错误处理。项目中采用try/catch包裹查询操作asyncgetCardList(){letconditionnewcloudDatabase.DatabaseQuery(Tool);try{this.cardListawaitthis.agcDataBase!!.query(condition)hilog.info(0x0000,testTag,Succeeded in querying data, result:${JSON.stringify(this.cardList)});}catch(err){hilog.error(0x0000,testTag,Failed to query data, code:${err.code}, message:${err.message});}}对于非关键数据如单词列表查询失败时返回空数组asyncgetWordList():PromiseWord[]{try{this.conditionnewcloudDatabase.DatabaseQuery(Word);letuuidawaitUserInfoManager.getUserInfo()?.unionIDthis.condition.equalTo(userId,uuid)returnawaitthis.agcDataBase?.query(this.condition)asWord[]}catch(err){return[]}}错误处理建议场景处理方式关键数据查询失败使用hilog.error记录UI 显示错误提示非关键数据查询失败返回空数组UI 显示暂无数据写入操作失败catch中提示用户重试网络不可用结合本地缓存提供离线体验7. UI 数据绑定查询结果直接绑定到State变量实现数据驱动 UI 更新StatecardList:Tool[][]BuilderCardLayout(){Grid(this.scroller){ForEach(this.cardList,(data:Tool,index:number){GridItem(){Column(){Column({space:5}){Row(){Text(data.name).fontWeight(FontWeight.Bold).fontColor(Color.White);Text(复习记忆).fontSize(10).fontColor(Color.White)}.width(100%).justifyContent(FlexAlign.SpaceBetween);}.width(100%).padding(10)}.backgroundImage(data.cover).width(100%).aspectRatio(1);}.onClick((){if(index1){this.pageContext.openPage({routerName:WordCardPage},true);}elseif(index0){this.pageContext.openPage({routerName:SentenceCardPage},true);}});});}.columnsTemplate(1fr 1fr).columnsGap(10).rowsGap(10)}单词列表页面无数据时显示空状态if(this.wordList.length0){Column({space:15}){Image($r(app.media.ic_no_data)).width(50)Text(点击对话记录中的单词可添加到单词卡片).fontSize(12)Text(暂无单词卡片).fontColor($r(app.color.color_divider)).fontSize(12)}.layoutWeight(1).justifyContent(FlexAlign.Center)}else{List({space:10}){ForEach(this.wordList,(word:Word,index:number){ListItem(){Column({space:10}){Row({space:5}){Text(word.name).fontWeight(FontWeight.Bold).fontSize(18)Image($r(app.media.ic_listening)).width(24).onClick((){this.model.download(word.ttsUrl!!).then((name:string){AudioUtils.getInstance().startPlay(getContext(this).cacheDirname)})})Blank()}.width(100%)Text(word.pronunciation).fontSize(12).width(100%)Text(word.means).fontSize(14).fontStyle(FontStyle.Italic)}.padding(12).alignItems(HorizontalAlign.Start)}.backgroundColor($r(app.color.color_card)).borderRadius(12)})}.layoutWeight(1)}8. DatabaseQuery 条件构建DatabaseQuery支持多种条件构建方式方法说明示例equalTo(field, value)等值查询condition.equalTo(userId, uuid)lessThan(field, value)小于condition.lessThan(age, 18)greaterThan(field, value)大于condition.greaterThan(score, 60)orderByDesc(field)降序排列condition.orderByDesc(date)orderByAsc(field)升序排列condition.orderByAsc(name)limit(count)限制返回数量condition.limit(10)多条件组合可以链式调用多个条件方法letconditionnewcloudDatabase.DatabaseQuery(Word);condition.equalTo(userId,uuid).orderByDesc(name).limit(20);小结本篇围绕 HarmonyOS 云数据库的核心操作展开讲解连接云数据库cloudDatabase.zone(name)获取DatabaseZone实例定义云对象继承DatabaseObject实现naturalbase_ClassName()指定表名查询数据DatabaseQueryT构建条件 →zone.query(condition)执行查询数据隔离condition.equalTo(userId, uuid)实现用户维度过滤写入数据zone.upsert(data)实现插入或更新错误处理try/catch包裹异步操作查询失败返回空数组UI 绑定查询结果直接赋值State变量驱动界面自动刷新云数据库为柚兔学伴实现了单词本、长难句等学习数据的端云同步用户在不同设备上都能获取一致的学习进度。

相关新闻

前端工程师收藏!2026年大模型风口,你的进阶“逃生”指南

前端工程师收藏!2026年大模型风口,你的进阶“逃生”指南

随着大模型技术成熟,前端开发岗位面临挑战。本文为前端工程师提供转型AI Agent开发的必要性、可行性及完整路径,对比技术栈、分析核心优势,构建知识图谱,助你在大模型时代把握机遇,实现职业进阶。 前端已死&#xff0c…

2026/7/23 16:44:38阅读更多 →
切问学术使用方法全解析 新手快速上手操作指南

切问学术使用方法全解析 新手快速上手操作指南

很多时候,你和同门在效率与视野上的差距,并非源于智力或努力,而在于信息获取与处理的“工具差”。当别人还在用传统方式大海捞针时,有人已经用新工具建好了知识雷达。尤其在查找和消化国外文献这个核心环节,工具带来的…

2026/7/23 16:42:38阅读更多 →
后端工程师转型AI大模型开发的核心技能与路径

后端工程师转型AI大模型开发的核心技能与路径

1. 后端工程师转型AI大模型开发的必要性作为一名拥有多年后端开发经验的工程师,我深刻感受到AI大模型技术带来的行业变革。传统后端开发虽然仍是企业系统的基石,但AI能力的引入正在重塑技术栈和职业发展路径。2023年以来,大模型应用呈现爆发式…

2026/7/23 16:42:38阅读更多 →
ARM Cortex-M4F异常屏蔽与双栈机制:FAULTMASK、BASEPRI、CONTROL寄存器实战解析

ARM Cortex-M4F异常屏蔽与双栈机制:FAULTMASK、BASEPRI、CONTROL寄存器实战解析

1. 项目概述与核心价值 在嵌入式系统,尤其是基于ARM Cortex-M4F这类高性能微控制器的开发中,异常和中断管理是区分新手与资深工程师的一道分水岭。很多开发者最初接触中断时,往往只停留在“配置NVIC、编写ISR”的层面,但当系统复杂…

2026/7/23 17:56:54阅读更多 →
单网口电脑安装openwrt软路由做单臂路由

单网口电脑安装openwrt软路由做单臂路由

第一步,依次输入运行firstboot和reboot,重置软路由配置(本文软路由来自恩山无线论坛)。第二步,将软路由的接口lan的物理接口从eth0更换为eth0.1,创建接口wan,将接口wan绑定物理接口eth0.2&#…

2026/7/23 17:56:54阅读更多 →
openwrt软路由重置firstboot重启reboot关机poweroff

openwrt软路由重置firstboot重启reboot关机poweroff

重置,恢复出厂设置,先执行firstboot命令,再执行reboot命令,过了几秒钟才会响应。重启设备,执行reboot命令。设备关机,执行poweroff命令。

2026/7/23 17:56:54阅读更多 →
【论文解读】AeroAct:训练用未来视频当“后果监督“,部署丢掉视频只解码轨迹——World-Action 模型第一次飞上真无人机

【论文解读】AeroAct:训练用未来视频当“后果监督“,部署丢掉视频只解码轨迹——World-Action 模型第一次飞上真无人机

论文:AeroAct(北京理工大学自动化学院 arXiv 2026) 发布时间:2026 年 7 月(arXiv:2607.14997) 作者:Xinhong Zhang、Qiyuan Zhu、Yubo Huang、Haolin Chen(共一)等&…

2026/7/23 17:56:54阅读更多 →
Nature Methods最新发布:多层级脑图谱工具Siibra,让脑科学数据终于有了自己的通用坐标系

Nature Methods最新发布:多层级脑图谱工具Siibra,让脑科学数据终于有了自己的通用坐标系

脑科学研究长期受困于“数据孤岛”——从显微切片到全脑成像,不同尺度、模态的数据集散落各处,缺乏统一的解剖学框架来整合与互操作。Siibra工具直击这一痛点,通过构建多层级人脑图谱,将细胞构筑、纤维连接与功能影像等多源数据锚…

2026/7/23 17:56:54阅读更多 →
ADC转换汇总(采样原理、取平均、精度等)

ADC转换汇总(采样原理、取平均、精度等)

目录: 一、外围硬件电路 1、ADC测量时噪声原因与消除 2、ADC端口保护电路 3、低噪声参考电源电路 二、采样原理、采样频率与采样率 1、ADC采样原理 2、采样频率与采样率 3、AD转换器的选择 三、电流检测采样值的高效处理 四、N次采样去最大最小求平均

2026/7/23 17:54:53阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/23 0:56:31阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/23 0:56:31阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 0:56:31阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:00:28阅读更多 →
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:28阅读更多 →
油泥处理设备哪里能买到

油泥处理设备哪里能买到

油泥处理设备哪里有?这是许多从事油田、炼化、清罐业务的从业者最关心的问题。根据河南三丰环保设备有限公司的行业经验,选购油泥处理设备的核心在于设备能否适配当地环保法规与原料特性,而非单纯看价格。该公司总经理王钦田先生指出&#xf…

2026/7/23 0:00:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/22 22:56:18阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/22 18:55:50阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/22 18:55:50阅读更多 →