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/10/10 12:29:21 阅读更多 →
免费投票工具软件有哪些|2026年6款主流投票小程序实测对比

免费投票工具软件有哪些|2026年6款主流投票小程序实测对比

线上投票已成为企业评优、校园赛事、社区活动等场景的常用工具。市面上的免费投票小程序种类繁多,但功能、定位和免费策略差异明显。本文基于2026年多轮实测数据,对评选星、人人微投票、天天评选、365评选、腾讯投票、问卷星六款主流工具进行横向对比&am…

2026/10/2 12:52:39 阅读更多 →
品牌年轻化有效性诊断:从视觉更新到价值再连接

品牌年轻化有效性诊断:从视觉更新到价值再连接

一、问题背景:外观更新不等于关系更新 在品牌资料整理中,常见现象是外部视觉、内容语气和渠道呈现已经更新,但用户对品牌的核心判断并没有发生变化。对于食品企业而言,外观更新只能改变识别方式,不能自动说明产品为何适…

2026/10/1 19:18:09 阅读更多 →

最新新闻

【单片机课设毕设项目】基于物联网的居室空气质量监测与自动通风补光系统设计 基于单片机的室内环境综合参数检测与手机端告警装置设计(030125)

【单片机课设毕设项目】基于物联网的居室空气质量监测与自动通风补光系统设计 基于单片机的室内环境综合参数检测与手机端告警装置设计(030125)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/10/11 9:35:44 阅读更多 →
AI算力评估报告怎么读?EFLOPS口径、服务器市场与行业排名的落地解析

AI算力评估报告怎么读?EFLOPS口径、服务器市场与行业排名的落地解析

简介:《2022-2023中国人工智能计算力发展评估报告》由浪潮信息发布,面向关注算力产业趋势的技术决策者、AI从业者与行业研究人员,系统呈现中国AI计算力发展全貌。报告共32页,基于IDC调研数据,围绕芯片、服务器、计算架…

2026/10/11 9:35:44 阅读更多 →
一文读懂 PoE+Modbus TCP 温湿度传感器布线规范与故障排查

一文读懂 PoE+Modbus TCP 温湿度传感器布线规范与故障排查

以太网型温湿度传感器:PoE供电与Modbus TCP工业监控部署指南盛世宏博以太网温湿度传感器引言在机房动环、智慧档案库房、配电室、无尘车间等工业监控场景,环境温湿度、露点数据是设备安全、档案长期保存的核心监测指标。传统RS485总线、4-20mA模拟量变送…

2026/10/11 9:35:44 阅读更多 →
老显卡UEFI黑屏亮度失灵?GOP更新刷VBIOS实战指南

老显卡UEFI黑屏亮度失灵?GOP更新刷VBIOS实战指南

简介:这是面向AMD与Nvidia显卡用户的GOP更新工具包,适用于Intel平台主板搭配A卡或N卡、遇到显示输出异常或性能优化需求的场景。工具通过刷新显卡GOP/EFI ROM,帮助显卡与BIOS及新系统保持兼容,对多显示器、高分辨率输出和启动画面…

2026/10/11 9:35:44 阅读更多 →
SSM框架实战:Java超市管理系统的数据库设计与实现全解析

SSM框架实战:Java超市管理系统的数据库设计与实现全解析

如果你正在为Java课程设计或毕业设计发愁,那“java_ssm27基于Java的超市管理系统”这类项目你一定不陌生。它基本上是国内计算机专业里出现频率最高的实战题目之一,核心是用SSM框架(Spring、SpringMVC、MyBatis)实现一套包含商品管…

2026/10/11 9:35:44 阅读更多 →
Jenkins最新版本2.585修改插件源的方法

Jenkins最新版本2.585修改插件源的方法

前言: Jenkins安装完成后需要下载多个插件,而国外插件源升级站点下载非常慢经常会出现超时的错误影响效率。所以最好的方法是当jenkins安装完成后修改插件源升级站点的地址。关于Jenkins2.585版本的安装方法参见、、。 一、修改更新站点地址 1、在Jenk…

2026/10/11 9:34:43 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →