数据模型——饮食记录

数据模型——饮食记录

本次实验完成饮食记录的数据模型,如下图所示

在这里插入图片描述

该饮食记录模型与上次的记录项数据模式定义处理方式相同,我们首先分析其数据结构,我们发现首先有早餐、午餐、晚餐等记录类型数据模型,其包括了id、类型名称、类型图标、类型推荐最小和最大卡路里等。在每个类型中又可以添加记录项,记录项也有id、类型id、卡路里总数、和上节课定义的记录项相同的数据项和食品数量或运动时长等组成的记录项数据模型。

记录类型数据模型

export default class RecordType{/*** 类型id*/id: number/*** 类型名称*/name: ResourceStr/*** 类型图标*/icon: ResourceStr/*** 类型推荐最小卡路里*/min: number/*** 类型推荐最大卡路里*/max: numberconstructor(id: number, name: ResourceStr, icon: ResourceStr, min: number = 0, max: number = 0) {this.id = idthis.name = namethis.icon = iconthis.min = minthis.max = max}
}

可以看出min和max设置了默认可选值,因为当类型为运动时,没有类型推荐最小卡路里、类型推荐最大卡路里

import RecordType from '../viewmodel/RecordType'enum RecordTypeEnum {/*** 早餐*/BREAKFAST,/*** 午餐*/LUNCH,/*** 晚餐*/DINNER,/*** 加餐*/EXTRA_MEAL,/*** 运动*/WORKOUT
}/*** 记录类型常量*/
const RecordTypes: RecordType[] = [new RecordType(0, $r("app.string.breakfast"), $r("app.media.ic_breakfast"), 423, 592),new RecordType(1, $r("app.string.lunch"), $r("app.media.ic_lunch"), 592, 761),new RecordType(2, $r("app.string.dinner"), $r("app.media.ic_dinner"), 423, 592),new RecordType(3, $r("app.string.extra_meal"), $r("app.media.ic_extra_m"), 0, 169),new RecordType(4, $r("app.string.workout"), $r("app.media.ic_workout")),
]export {RecordTypes, RecordTypeEnum}

这里设置RecordTypeEnum枚举的作用与上次相同,有助于每一项数据项能方便的找到其所在的类型。

记录项数据模型

import RecordItem from './RecordItem'/*** 饮食记录的页面数据模型*/
export default class RecordVO {/*** 记录id*/id: number/*** 饮食记录类型*/typeId: number/*** 卡路里总数*/calorie: number/*** 记录中的食物或运动信息*/recordItem: RecordItem/*** 食物数量或运动时长,如果是运动信息则无*/amount: number = 0
}

在其中recordItem的类型是上次我们定义的RecordItem数据模型,方便我们直接使用上次定义的数据模型中的数据。

在这里插入图片描述

如图所示,RecordModel我们采用了关系型数据库来保存记录项的数据,通过关系型数据库来进行数据操作,这样做的原因是因为,这部分数据是可以根据日期进行查询的,还可以执行删除操作,所以不能像其他数据一样保存在内存中,必须保存在关系型数据库中才能进行

持久化保存。

为了操作数据库方便,我们定义了数据库通用工具类

import common from '@ohos.app.ability.common';
import relationalStore from '@ohos.data.relationalStore';
import { ColumnInfo, ColumnType } from '../bean/ColumnInfo';
import Logger from './Logger';const DB_FILENAME: string = 'HeiMaHealthy.db'class DbUtil {rdbStore: relationalStore.RdbStoreinitDB(context: common.UIAbilityContext): Promise<void> {let config: relationalStore.StoreConfig = {name: DB_FILENAME,securityLevel: relationalStore.SecurityLevel.S1}return new Promise<void>((resolve, reject) => {relationalStore.getRdbStore(context, config).then(rdbStore => {this.rdbStore = rdbStoreLogger.debug('rdbStore 初始化完成!')resolve()}).catch(reason => {Logger.debug('rdbStore 初始化异常', JSON.stringify(reason))reject(reason)})})}createTable(createSQL: string): Promise<void> {return new Promise((resolve, reject) => {this.rdbStore.executeSql(createSQL).then(() => {Logger.debug('创建表成功', createSQL)resolve()}).catch(err => {Logger.error('创建表失败,' + err.message, JSON.stringify(err))reject(err)})})}
//添加通用新增方法insert(tableName:string,obj:any,columns:ColumnInfo[]){return new Promise((resolve,reject)=>{//1.构建新增的数据let value=this.buildValueBucket(obj,columns)//2.新增this.rdbStore.insert(tableName,value,(err,id)=>{if (err) {Logger.debug('新增失败!',JSON.stringify(err))reject(err)}else {Logger.debug('新增成功!新增id:',id.toString())resolve(id)}})})}//通用删除delete(predicates:relationalStore.RdbPredicates){return new Promise((resolve,reject)=>{//1.删除this.rdbStore.delete(predicates,(err,rows)=>{if (err) {Logger.debug('删除失败!',JSON.stringify(err))reject(err)}else {Logger.debug('删除成功!删除行数:',rows.toString())resolve(rows)}})})}//批量查询queryForList<T>(predicates:relationalStore.RdbPredicates,columns:ColumnInfo[]):Promise<T[]>{return new Promise((resolve,reject)=>{//1.删除this.rdbStore.query(predicates,columns.map(info=>info.columnName),(err,result)=>{if (err) {Logger.debug('查询失败!',JSON.stringify(err))reject(err)}else {Logger.debug('查询成功!查询行数:',result.rowCount.toString())resolve(this.parseResultSet(result,columns))}})})}//解析resultSETparseResultSet<T>(result:relationalStore.ResultSet,columns:ColumnInfo[]):T[]{//1.声明最终返回结果let arr=[]//2.判断是否有结果if (result.rowCount<=0) {return arr;}//3.处理结果while (!result.isAtLastRow) {//3.1 去下一行result.goToNextRow()//3.2 解析该行数据,转为结果对象格式let obj={}columns.forEach(info=>{let val=nullswitch (info.type){case ColumnType.LONG:val=result.getLong(result.getColumnIndex(info.columnName))break;case ColumnType.DOUBLE:val=result.getDouble(result.getColumnIndex(info.columnName))break;case ColumnType.STRING:val=result.getString(result.getColumnIndex(info.columnName))break;case ColumnType.BLOB:val=result.getBlob(result.getColumnIndex(info.columnName))break;}obj[info.name]=val;})//3.3 将对象填充到数组arr.push(obj)}return arr;}buildValueBucket(obj:any,columns:ColumnInfo[]):relationalStore.ValuesBucket{//1.构建数据let value={}columns.forEach(info=>{let val=obj[info.name]if (typeof val !=='undefined') {value[info.columnName]=val}})return value
}}let dbUtil: DbUtil = new DbUtil();export default dbUtil as DbUtil

可以看出,我们只需要提供DBUtil中所需方法的参数,即可进行增删改查操作,适用于所有数据库。但是想要实现该功能,需要在EntryAbility中初始化RDB工具和数据库中表的建立:

async  onCreate(want, launchParam) {//1.加载用户首选项PreferenceUtil.loadPreference(this.context)//2.初始化日期AppStorage.SetOrCreate(CommonConstants.RECORD_DATE,DateUtil.beginTimeOfDay(new Date()))//3.初始化RDB工具await DbUtil.initDB(this.context)//4.创建record表的创建DbUtil.createTable(RecordModel.getCreateTableSql())hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');}

在完成这样后我们便可以在RecordModel中调用DBUtil所提供的方法,进行record数据表的增删改查操作,从而完成各种业务逻辑。

观察下面的代码,const CREATE_TABLE_SQL提供给了EntryAbility进行数据库中record表的建立,而且只有列名与数据库列名的映射正确,才能使自己定义的数据模型能正确使用数据库。

/*** 数据库建表语句*/
import relationalStore from '@ohos.data.relationalStore'
import { ColumnInfo, ColumnType } from '../common/bean/ColumnInfo'
import RecordPO from '../common/bean/RecordPO'
import DbUtil from '../common/utils/DbUtil'
const CREATE_TABLE_SQL: string = `CREATE TABLE IF NOT EXISTS record (id INTEGER PRIMARY KEY AUTOINCREMENT,type_id INTEGER NOT NULL,item_id INTEGER NOT NULL,amount DOUBLE NOT NULL,create_time INTEGER NOT NULL)`
//列名与数据库列名的映射
const COLUMNS: ColumnInfo[] = [{name: 'id', columnName: 'id', type: ColumnType.LONG},{name: 'typeId', columnName: 'type_id', type: ColumnType.LONG},{name: 'itemId', columnName: 'item_id', type: ColumnType.LONG},{name: 'amount', columnName: 'amount', type: ColumnType.DOUBLE},{name: 'createTime', columnName: 'create_time', type: ColumnType.LONG}
]const TABLE_NAME = 'record'
const ID_COLUMN = 'id'
const DATE_COLUMN = 'create_time'class RecordModel {getCreateTableSql(): string {return CREATE_TABLE_SQL}
//插入insert(record:RecordPO){return DbUtil.insert(TABLE_NAME,record,COLUMNS)}
//删除deleteById(id:number){//1.删除条件let predicates=new relationalStore.RdbPredicates(TABLE_NAME)predicates.equalTo(ID_COLUMN,id)//2.删除return DbUtil.delete(predicates)}//查找(按日期)listByDate(date:number){//1.查询条件let predicates=new relationalStore.RdbPredicates(TABLE_NAME)predicates.equalTo(DATE_COLUMN,date)//2.查询DbUtil.queryForList(predicates,COLUMNS)}
}let recordModel = new RecordModel()export default recordModel as RecordModel

下次课我们将完成利用此数据模型,实现保存不同日期的饮食记录的数据保存功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30208.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI人工智能产品经理,就该这么学!

前言 想入行AI人工智能产品经理&#xff0c;该如何学习呢&#xff1f; 随时AI的兴起&#xff0c;AI产品经理开始爆火&#xff0c;很多功能性产品经理想转行做AI产品经理。转行的原因&#xff0c;这个仁者见仁智者见智。唯一的共同点就是&#xff0c;大家都看好AI行业的发展前景…

Java 诊断神器 Arthas使用笔记

Arthas 是一款开源在线 Java 诊断工具&#xff0c;采用命令行交互模式&#xff0c;支持 web 端在线诊断&#xff0c;同时提供丰富的 Tab 自动补全功能&#xff0c;进一步方便进行问题的定位和诊断。得益于 Arthas 强大且丰富的功能。 1.JDK原生定位工具 平时开发中会用到JDK中…

edge如何找包已经安装的插件。

我的目录&#xff1a;C:\Users\Administrator\AppData\Local\Microsoft\Edge\User Data\Default\Extensions 如图&#xff1a; 如何我要打包如下图 注意iD的名字 多次操作选择到ID的目录&#xff0c;再向下。 如上图之后。打包。 显示成功 并提供地址。 找到相应地址&#x…

监控员工上网软件有哪些|4款好用的员工上网行为管理软件推荐

在当今数字化办公环境中&#xff0c;确保网络安全、提升工作效率、以及规范员工上网行为成为企业管理的重要组成部分。 为此&#xff0c;一套高效的员工上网行为管理软件显得尤为关键。 本文将为您推荐五款市场上广受好评的员工上网行为管理软件&#xff0c;帮助您有效监控与管…

linux离线安装chrony服务校准时间

基础环境 Linux forlinx 5.10.35 #53 SMP PREEMPT Thu Mar 30 01:04:19 CST 2023 aarch64 aarch64 aarch64 GNU/Linux chrony源码包 下载地址&#xff1a;https://download.tuxfamily.org/chrony/ 以chrony-4.5.tar.gz举例说明 详细步骤 1.解压chrony tar zxvf chrony-4.…

【Spine学习14】之 裁剪

1、新建裁剪 2、在页面中随便点几下 圈出对应位置 3、点编辑裁剪 或者按空格键 退出编辑模式&#xff0c; 页面就只剩下对应区域&#xff0c;这个区域可以任意拖动 放大缩小显示。 tips&#xff1a; 如果手动选择区域描绘不准确&#xff0c;可以启用对应图片的网格 然后复制…

无监督学习:从理论到实践的全面指南

本文深入讲解了无监督学习中的K-means、层次聚类、密度聚类、PCA、t-SNE和自编码器算法&#xff0c;涵盖其原理、数学基础、实现步骤及应用实例&#xff0c;并提供了详细的代码示例。 关注作者&#xff0c;复旦AI博士&#xff0c;分享AI领域全维度知识与研究。拥有10年AI领域研…

外链应该怎么做才有效?

做有效的外链&#xff0c;关键在于策略和执行&#xff0c;高质量的独立站外链就是一个不错的选择&#xff0c;确保是dofollow&#xff0c;每一条都被谷歌收录&#xff0c;并保证长期留存&#xff0c;至少一年以上&#xff0c;这种外链就是能发挥最大效果的外链&#xff0c;名为…

全新防关联技术出炉:亚马逊测评环境优化,下单成功率大提升

在竞争激烈的测评行业中&#xff0c;构建一个稳定且高效的环境系统成为了制胜的关键。然而&#xff0c;市场上现有的环境方案如虚拟机、模拟机、GCS、云手机、VPS等不仅成本高昂&#xff0c;而且面临着在风控严格的平台上如亚马逊难以逃脱检测的挑战&#xff0c;进而影响了测评…

Memory use report提示信息

Memory use report: Heap dump has been created at C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2021.3\tmp\hprof-temp\heapDump-idea-1718785956302.hprof. It will be analyzed next time you start IntelliJ IDEA.Memory use report提示信息 Memory use…

【两数之和】

两数之和 一、题目二、暴力解法三、哈希表四、map字典1.基本方法.set()添加键值对.get()通过键获取值.has()判断map是否有这个键 2.map和set的联系和区别共同点共同点MapSet 一、题目 二、暴力解法 三、哈希表 解题思路&#xff1a;将nums的元素依次以键值对的方式存储在map字典…

MacOS之解决:开盖启动问题(七十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

mysql中返回日期格式带有T、Java解决返回日期格式带 ‘T‘ 问题、MySQL查询日期为什么带T、java.util.Date()类型为什么有T

文章目录 一、场景描述&#xff1a;Mysql返回日期格式带有T二、解决方法2.1、方法一&#xff1a;通过注解格式化2.2、方法二&#xff1a;通过全局配置2.3、方法三&#xff1a;查询时手动转换时间格式 三、mysql 数据库时间类型数据为什么有T3.1、什么是ISO 8601格式 四、java中…

储备教师和正式教师的区别是什么?

当谈论教育行业的未来&#xff0c;是否曾想过&#xff0c;那些被称为"储备教师"的群体&#xff0c;与我们熟知的"正式教师"之间&#xff0c;有何本质的区别&#xff1f; 储备教师&#xff0c;顾名思义&#xff0c;是学校为了应对未来可能的教学需求而提前招…

Redis 集群 - 数据分片算法

前言 广义的集群&#xff1a;只要是多个机器构成了一个分布式系统&#xff0c;都可以被称为集群。 狭义的集群&#xff1a;redis 的集群模式&#xff0c;这个集群模式下&#xff0c;主要是解决存储空间不足的问题。 Redis 集群 redis 采用主从结构&#xff0c;可以提高系统的可…

cs144 LAB1 基于滑动窗口的碎片字节流重组器

一.StreamReassembler.capacity 的意义 StreamReassembler._capacity 的含义&#xff1a; ByteStream 的空间上限是 capacityStreamReassembler 用于暂存未重组字符串片段的缓冲区空间 StreamReassembler.buffer 上限也是 capacity蓝色部分代表了已经被上层应用读取的已重组数…

神火股份电子商务平台(数字化招采平台),构建企业数字活力

为推进数字化转型升级进程&#xff0c;神火股份携手信源信息建设电子商务平台&#xff0c;近日&#xff0c;该平台已实现验收&#xff0c;为企业高质量发展注入“数字活力”。 河南神火煤电股份有限公司&#xff08;简称“神火股份”&#xff09;是以煤炭、发电、电解铝生产及…

2024年CCSK认证培训招生简章公开

CCSK认证培训背景 本课程旨在确保与云计算相关的从业人员对云安全威胁和云安全最佳 实践有一个全面的了解和广泛的认知。包含了广泛的云安全知识&#xff0c;涵 盖了体系结构、合规治理、加密和虚拟化等主题。自2010年推出以 来&#xff0c;成千上万的IT和安全专业人员通过CCSK…

snmp-check一键获取SNMP信息(KALI工具系列二十一)

目录 1、KALI LINUX 简介 2、snmp-check工具简介 3、在KALI中使用onesixtyone 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、操作示例 4.1 SNMP 检查 4.2 指定 SNMP 端口 4.3 指定社区字符串 4.4 详细输出 4.5 指定多项 5、总结 1、KALI LINUX 简介…

Danikor智能拧紧轴控制器过压维修知识

【丹尼克尔拧紧轴控制器故障代码维修】 【丹尼克尔Danikor控制器维修具体细节】 丹尼克尔拧紧轴控制器作为一种高精度的电动拧紧工具&#xff0c;广泛应用于各种工业生产线。然而&#xff0c;在使用过程中&#xff0c;由于各种原因&#xff0c;可能会出现Danikor扭矩扳手控制…