当前位置: 首页 > news >正文

端侧调用云数据库获取业务数据

1、一键生成目标对象类型类文件

云数据库支持从端侧或者云侧云函数访问数据库,代码涉及调用云数据库时,需要引入对应云数据库对象类型的类文件。DevEco当前支持为对象类型一键生成类文件,供开发者在端侧或云侧云函数开发时引用,以下为生成端侧对象类型类文件。

  • 在云侧工程中,右击目标对象类型(以Feeding为例),选择“Generate Client Model”。

image-20250622215537942

  • 选择生成的Client Model文件存放的端侧目录。

image-20250622215544882

  • 点击“OK”。指定目录下生成对应对象类型的Client Model文件,后续开发者便可以在端侧代码中方便地引用该Client Model。
import { Feeding } from '../model/Feeding';

2、在端侧工程操作云数据库

云开发服务能力为开发者提供了直接操作云数据库的模块,该模块可以对云数据库进行数据写入、查询、删除等操作。

端侧工程查询云数据库数据分为三步,第一步引入云数据库模块组件;第二步构建查询条件;第三步从存储区获取满足查询条件的数据。

1)引入云数据库模块组件和端侧模型类Feeding。

import { cloudDatabase } from '@kit.CloudFoundationKit';
import { Feeding } from '../model/Feeding';

2)构建查询条件

云数据库模块提供了丰富的谓词查询来构建查询条件,包括以下谓词:

方法说明
equalTo(fieldName: string, value: FieldType)添加实体类中某个字段的值等于指定值的查询条件
notEqualTo(fieldName: string, value: FieldType)添加实体类中某个字段的值不等于指定值的查询条件
beginsWith(fieldName: string, value: FieldType)添加实体类中string类型字段值以指定子串开头的查询条件。
endsWith(fieldName: string, value: FieldType)添加实体类中string类型字段值以指定子串结尾的查询条件。
contains(fieldName: string, value: FieldType)添加实体类中字符串类型字段值包含指定子字符串的查询条件。
greaterThan(fieldName: string, value: FieldType)添加实体类字段值大于指定值的查询条件。
greaterThanOrEqualTo(fieldName: string, value: FieldType)添加实体类字段值大于或等于指定值的查询条件。
lessThan(fieldName: string, value: FieldType)添加实体类字段值小于指定值的查询条件。
lessThanOrEqualTo(fieldName: string, value: FieldType)添加实体类字段值小于或等于指定值的查询条件。
in(fieldName: string, values: FieldType[])添加实体类字段值包含在指定数组中的查询条件。
isNull(fieldName: string)添加实体类某字段值为空的查询条件。
isNotNull(fieldName: string)添加实体类某字段值不为空的查询条件。
orderByAsc(fieldName: string)按指定字段升序对查询结果进行排序。
orderByDesc(fieldName: string)按指定字段降序对查询结果进行排序。
limit(count: number, offset?: number)指定返回的查询结果集中的数据记录条数。如果不设置offset,则默认从首个对象开始获取前count个对象。
beginGroup()调用此方法是为了放置左括号“(”附加到任何查询条件并将右括号“)”与相同的查询连接起来组合使用。
endGroup()调用此方法是为了放置右括号“)”附加到任何查询条件并将左括号“(”与相同的查询连接起来组合使用。
or()使用or运算组合两个条件并返回两个查询结果的并集。
and()使用and运算组合两个条件并返回两个查询结果的交集。

我们以查询当前宝宝喂养记录为例,需要用到greaterThanOrEqualTolessThanOrEqualTo两个属性来获取当天喂养记录。

condition: cloudDatabase.DatabaseQuery<Feeding> = new cloudDatabase.DatabaseQuery(Feeding);
condition.greaterThanOrEqualTo("startTime", this.currentDateTime.setHours(0, 0, 0, 0)).and().lessThanOrEqualTo("startTime", this.currentDateTime.setHours(23, 59, 59, 999));

3)查询数据

构建符合业务逻辑的查询条件之后,调用云数据库模块提供通过存储区名称初始化云数据库实例。云数据库实例具备以下能力:

方法说明
query<T extends DatabaseObject>(condition: DatabaseQuery<T>)通过查询条件查询数据
calculateQuery<T extends DatabaseObject>(condition: DatabaseQuery<T>, fieldName: string, calculate: QueryCalculate)从数据库中查询符合条件的数据,并对指定字段进行算术计算。
`upsert(objectList: T[]T)`
`delete(objectList: T[]T)`
// 构建查询条件
const queryCondition = this.condition.greaterThanOrEqualTo("startTime", this.currentDateTime.setHours(0, 0, 0, 0)).and().lessThanOrEqualTo("startTime", this.currentDateTime.setHours(23, 59, 59, 999));
const result = await this.databaseZone.query(queryCondition);

完成的代码:

currentDateTime: Date = new Date();
condition: cloudDatabase.DatabaseQuery<Feeding> = new cloudDatabase.DatabaseQuery(Feeding);
private databaseZone = cloudDatabase.zone("default");@State allFeedingList: Feeding[] = [];// 查询当前喂养记录信息
async queryAllFeeding() {try {// 构建查询条件const queryCondition = this.condition.greaterThanOrEqualTo("startTime", this.currentDateTime.setHours(0, 0, 0, 0)).and().lessThanOrEqualTo("startTime", this.currentDateTime.setHours(23, 59, 59, 999));const result = await this.databaseZone.query(queryCondition);if (result.length > 0) {this.allFeedingList = result;}} catch (error) {// 异常处理this.allFeedingList = [];}
}async aboutToAppear(): Promise<void> {this.queryAllFeeding();
}// 页面
if (this.allFeedingList.length > 0) {List() {ForEach(this.allFeedingList, (item: Feeding) => {ListItem() {Column({ space: 8 }) {Row() {Text(`${item.type}喂养`)Text(`${item.startTime.toLocaleDateString()}`)}.width('100%').height(32).justifyContent(FlexAlign.SpaceBetween)if (item.type === '母乳') {Row() {Text(`左边喂养时长:${item.leftDuration}m`)Text(`右边喂养时长:${item.rightDuration}m`)}.width('100%').justifyContent(FlexAlign.SpaceBetween)}Text(`总喂养时长:${item.totalDuration}m`).width('100%').height(32)}.backgroundColor(0xf2f2f2).padding(12).borderRadius(8)}})}.width('90%').divider({strokeWidth: 2,color: Color.White})
}

4)新增数据

// 新增喂养记录
async insertFeeding(feeding: Feeding) {await this.databaseZone.upsert(feeding);
}

5)删除数据

// 删除数据
async deleteFeeding(feeding: Feeding) {await this.databaseZone.delete(feeding);
}

完整代码:

import { cloudFunction, cloudDatabase } from '@kit.CloudFoundationKit';
import { BusinessError, request } from '@kit.BasicServicesKit';
import { SymbolGlyphModifier } from '@kit.ArkUI';import { Feeding } from '../model/Feeding';interface BabyAge {years: number;months: number;days: number;totalDays: number;
}interface ResponseBody {code: number;desc: string;data: BabyAge
}@Entry
@Component
struct Index {controller: SearchController = new SearchController();@State birthday: string = "";@State callFunctionResult: BabyAge | undefined = undefined;currentDateTime: Date = new Date();condition: cloudDatabase.DatabaseQuery<Feeding> = new cloudDatabase.DatabaseQuery(Feeding);private databaseZone = cloudDatabase.zone("default");@State allFeedingList: Feeding[] = [];@State feeding: Feeding = new Feeding();@State isFeeding: boolean = false;@State startTime: Date = new Date();// 查询当前喂养记录信息async queryAllFeeding() {try {// 构建查询条件const queryCondition = this.condition.greaterThanOrEqualTo("startTime", this.currentDateTime.setHours(0, 0, 0, 0)).and().lessThanOrEqualTo("startTime", this.currentDateTime.setHours(23, 59, 59, 999));const result = await this.databaseZone.query(queryCondition);if (result.length > 0) {this.allFeedingList = result;}} catch (error) {// 异常处理this.allFeedingList = [];}}// 新增喂养记录async insertFeeding(feeding: Feeding) {await this.databaseZone.upsert(feeding);await this.queryAllFeeding();}// 删除数据async deleteFeeding(feeding: Feeding) {try {await this.databaseZone.delete(feeding);await this.queryAllFeeding();} catch (error) {const err: BusinessError = error;this.getUIContext().getPromptAction().showToast({message: err.message})}}async aboutToAppear(): Promise<void> {this.queryAllFeeding();}build() {Column({ space: 10 }) {Text("请先设置宝宝出生日期").fontColor(Color.Grey).height(54)Search({ controller: this.controller, value: this.birthday }).width('90%').height('54vp').searchIcon(new SymbolGlyphModifier($r('sys.symbol.calendar_badge_play')).fontColor([Color.Grey]).fontSize('30fp')).cancelButton({style: CancelButtonStyle.INVISIBLE}).borderRadius('8vp').onClick(() => {CalendarPickerDialog.show({selected: new Date(this.birthday),acceptButtonStyle: {style: ButtonStyleMode.EMPHASIZED},cancelButtonStyle: {fontColor: Color.Grey},onAccept: async (value) => {this.birthday = value.toLocaleDateString();console.info("calendar onAccept:" + JSON.stringify(value))let result: cloudFunction.FunctionResult = await cloudFunction.call({name: 'calculate-baby-age',version: '$latest',timeout: 10 * 1000,data: {birthday: this.birthday}});let body = result.result as ResponseBody;this.callFunctionResult = body.data;}})})if (this.callFunctionResult !== undefined) {Row() {Column({ space: 8 }) {Text(`我已经${this.callFunctionResult.years}岁了 ${this.callFunctionResult.months}${this.callFunctionResult.days}天了~`)Text(`我已经出生${this.callFunctionResult.totalDays}天了~`)}.width('100%')}.width('90%')Button(`${this.isFeeding ? '停止喂养' : '开始喂养'}`).backgroundColor(this.isFeeding ? Color.Orange : Color.Green).onClick(async () => {this.isFeeding = !this.isFeeding;if (this.isFeeding) {this.startTime = new Date();this.feeding.id = this.allFeedingList.length + 1;this.feeding.startTime = this.startTime;} else {this.feeding.totalDuration = new Date().getTime() - this.startTime.getTime();await this.insertFeeding(this.feeding);}})if (this.allFeedingList.length > 0) {List() {ForEach(this.allFeedingList, (item: Feeding) => {ListItem() {Column({ space: 8 }) {Row() {Text(`${item.type}喂养`)Text(`${item.startTime.toLocaleDateString()}`)}.width('100%').height(32).justifyContent(FlexAlign.SpaceBetween)Text(`总喂养时长:${item.totalDuration >= (60 * 1000) ? (item.totalDuration / (60 * 1000)) + 'm' : (item.totalDuration / 1000) + 's'}`).width('100%').height(32)Row() {Button("删除").onClick(async () => {this.getUIContext().getPromptAction().showDialog({title: '温馨提示',message: '确定要删除该喂养记录吗?',buttons: [{text: '取消',color: '#D3D3D3'},{text: '确定',color: '#FF5277'}],}).then(async data => {console.info('showDialog success, click button: ' + data.index);if (data.index === 1) {await this.deleteFeeding(item);}}).catch((err: Error) => {console.info('showDialog error: ' + err);})})}.width('100%')}.backgroundColor(0xf2f2f2).padding(12).borderRadius(8)}})}.width('90%').height(450).divider({strokeWidth: 2,color: Color.White})}}}.width('100%').height('100%')}
}

相关文章:

  • 【Datawhale组队学习202506】YOLO-Master task03 IOU总结
  • 从iPSC到成熟细胞,纳米生物材料如何当“向导”?
  • 【大模型微调】6.模型微调实测与格式转换导出
  • 核心概念解析:AI、数据挖掘、机器学习与深度学习的关系
  • Linux(3)
  • 数学:初步了解什么是“向量”
  • HarmonyOS NEXT端侧工程调用云侧能力实现业务功能
  • 扫雷中的数学原理
  • ToolsSet之:歌词编辑器
  • 【期末速成】编译原理
  • 【期末笔记】高频电子线路
  • 从零开始手写redis(16)实现渐进式 rehash map
  • 云侧工程云函数开发
  • 测试工程师实战:用 LangChain+deepseek构建多轮对话测试辅助聊天机器人
  • Effective C++学习笔记
  • DeepSeek15-揭密模型上下文协议(MCP)
  • [学习] C语言<string.h>中字符串函数全解析
  • java专题漏洞总结 + 靶场练习
  • 开源 python 应用 开发(二)基于pyautogui、open cv 视觉识别的工具自动化
  • 关于程序的基本要素的详细讲解(从属GESP一级内容)
  • 淮南建设网站/杭州最好的电商培训机构
  • python做网站guthub/网站seo应用
  • 海口网红美食餐厅/aso优化工具
  • 山东网站营销/专业seo推广
  • 大流量网站建设/清远新闻最新消息
  • 青岛自助建站软件/下载百度官方网站