数据模型——饮食记录

数据模型——饮食记录

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

在这里插入图片描述

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

记录类型数据模型

export default class RecordType{
  /**
   * 类型id
   */
  id: number
  /**
   * 类型名称
   */
  name: ResourceStr
  /**
   * 类型图标
   */
  icon: ResourceStr
  /**
   * 类型推荐最小卡路里
   */
  min: number
  /**
   * 类型推荐最大卡路里
   */
  max: number

  constructor(id: number, name: ResourceStr, icon: ResourceStr, min: number = 0, max: number = 0) {
    this.id = id
    this.name = name
    this.icon = icon
    this.min = min
    this.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.RdbStore

  initDB(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 = rdbStore
          Logger.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))
        }
      })
    })
  }

  //解析resultSET
  parseResultSet<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=null
        switch (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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

几个小实验

小实验 shh远程管理 ssh是一种安全通道协议&#xff0c;只能用来实现字符界面的远程登录。远程复制&#xff0c;远程文本传输。 ssh对通信双方的数据进行了加密。 用户名和密码登录 密钥对认证方式&#xff08;可以实现免密登录&#xff09; ssh 22 网络层 传输层 数据传…

龙虎斗(2018)c++

题目描述 输入 输出 样例输入&#xff0c;输出 输入 #1 输出 #1 6 2 2 3 2 3 2 3 4 6 5 2 输入 #2 输出 #2 6 …

最新技术:跨境电商源码,应对多国市场需求,让您轻松开展全球业务!

随着全球化进程的不断推进&#xff0c;跨境电商已成为企业拓展国际市场的重要途径。为了满足不同国家和地区消费者不断增长的需求&#xff0c;跨境电商源码应运而生&#xff0c;为企业提供了便捷高效的全球化业务发展方案。 一、全球化运营的关键 跨境电商源码的核心功能在于…

GaussDB技术解读——GaussDB架构介绍(五)

GaussDB架构介绍&#xff08;四&#xff09;从云原生关键技术架构&关键技术方案两方面对GaussDB云原生架构进行了解读&#xff0c;本篇将从关键技术方案的事务存储组件、SQL引擎组件、DCS组件、实时分析组件等方面继续介绍GaussDB云原生架构。 目录 事务存储组件 1、本地…

零基础入门学用Arduino 第四部分(三)

重要的内容写在前面&#xff1a; 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后&#xff0c;整体感觉是很好的&#xff0c;如果有条件的可以先学习一些相关课程&#xff0c;学起来会更加轻松&#xff0c;相关课程有数字电路…

《EDA技术》同步十三进制计数器实验报告

摘要&#xff1a; 本实验通过Multsim和Quartus软件完成对同步十三进制计数器的仿真&#xff0c;运用Quartus软件编VHDL程序&#xff0c;实现波形图的生成&#xff0c;并且运用Multsim软件进行电路图仿真。同时&#xff0c;加深 对数字电路和VHDL语言的理解&#xff0c;提高实验…

2024 年 Python 基于 Kimi 智能助手 Moonshot Ai 模型搭建微信机器人(更新中)

注册 Kimi 开放平台 Kimi&#xff1a;https://www.moonshot.cn/ Kimi智能助手是北京月之暗面科技有限公司&#xff08;Moonshot AI&#xff09;于2023年10月9日推出的一款人工智能助手&#xff0c;主要为用户提供高效、便捷的信息服务。它具备多项强大功能&#xff0c;包括多…

04 Pytorch tensor

一&#xff1a;老版本的 variable 二&#xff1a;新版 tensor 曾经&#xff1a;求导相关 如今&#xff1a;数据相关 –dtype: 张量的数据类型&#xff0c;三大类&#xff0c;共9种。torch.FloatTensor, torch.cuda.FloatTensor –shape: 张量的形状。如&#xff1a;&#x…

k8s学习--Kruise Rollouts 基本使用

文章目录 Kruise Rollouts简介什么是 Kruise Rollouts&#xff1f;核心功能 应用环境一、OpenKruise部署1.安装helm客户端工具2. 通过 helm 安装 二、Kruise Rollouts 安装2. kubectl plugin安装 三、Kruise Rollouts 基本使用(多批次发布)1. 使用Deployment部署应用2.准备Roll…

[Cloud Networking] SPDY 协议

文章目录 1. 背景2. SPDY 之前3. SPDY 项目目标4. SPDY 功能特点4.1 SPDY基本功能4.2 SPDY高级功能 1. 背景 TCP是通用的、可靠的传输协议&#xff0c;提供保证交付、重复抑制、按顺序交付、流量控制、拥塞避免和其他传输特性。 HTTP是提供基本请求/响应语义的应用层协议。 不…

网格布局之重复轨道

网格布局之重复轨道 欢迎关注&#xff1a;xssy5431 小拾岁月 参考链接&#xff1a;https://mp.weixin.qq.com/s/FQboZRMhdOFWqVDZ5JScDg 点击查看 使用场景 在网页开发中&#xff0c;我们尝尝会遇到宫格布局&#xff0c;比如&#xff1a;3 * 3&#xff0c;4 * 4布局等等。 …

6月19日(周三)A股行情总结:A股震荡收跌,恒生科技指数大涨3%,10年期国债期货转涨续创新高

内容提要 车路云概念延续昨日涨势&#xff0c;华铭智能20CM 3连板。贵金属及PEEK材料概念全日走强&#xff1b;港股有色金属及能源股走强&#xff0c;紫金矿业涨超3%&#xff0c;中石油涨超3%。国债期货午后全线转涨&#xff0c;10年期主力合约涨0.05%报104.925元&#xff0c;…

7zip安装后压缩包图标显示空白解决办法

记录安装7zip软件后&#xff0c;出现了如下的图标是空白的问题: &#xff08;虽然我最终解决了但是我不确定是哪一步起的作用&#xff0c;但是我也懒得再情景复现了。&#xff09; 我的解决过程是&#xff1a; 在开始菜单栏搜索“7zip ”然后点击“打开。 然后点击 &#xf…

HTTP!!!

HTTP 一 : 请求报文1.2 : 首行1.3 :请求头(header)1.4 : 空行1.5 : 正文 body 二: 响应报文2.2 : 首行 三 : URL 一 : 请求报文 一个HTTP 请求报文, 分成四个部分 首行 GET https://cn.bing.com/?FORMZ9FD1 HTTP/1.1请求头(header)空行正文(body) 1.2 : 首行 首行又分为三个…

CobaltStrike后渗透进阶篇

0x01 网络钓鱼攻击 钓鱼攻击简介 钓鱼攻击主要通过生成的木马诱使受害者运行后上线&#xff0c;其中木马一般都伪装成正常的程序。与此同时配合钓鱼网站可帮助攻击者模拟真实网站诱骗受害者访问&#xff0c;达到获取账号密码、上线木马等目的。接下来主要介绍后门程序的生成及…

自动化测试接口测试前的【准备及思路】

1、什么是接口测试 客户端&#xff08;前端&#xff09;与服务端&#xff08;后端&#xff09;的关系&#xff0c;一般小编会理解为“服务端负责赚钱养家&#xff0c;客户端负责貌美如花”。客户端更注重的是功能呈现及用户体验&#xff0c;怎么将强大的功能精彩的界面呈现给不…

云上战场:ToDesk云电脑、青椒云、顺网云全面对决

前言 记得端午放假期间&#xff0c;我已经在旅游的路上了&#xff0c;老板突然发短信&#xff0c;让我给他画个图&#xff0c;我手上的战斗机已经是十年前的老古董了(平常一直用的公司电脑&#xff0c;也没想过要换)&#xff0c;压根满足不了老板的任务要求&#xff0c;不得已&…

系统之家教你安装最新Win10 22H2版本!一看就会!

当前很多用户办公或学习都喜欢使用Win10系统&#xff0c;但很多新手用户不知道怎么操作才能安装上最新的Win10 22H2版本&#xff1f;接下来系统之家小编就给大家带来最简单的安装方法&#xff0c;帮助大家轻松快速给电脑安装上Win10系统最新版本22H2&#xff0c;体验22H2版本带…

Footer组件在home 、search 显示,在登录、注册隐藏

footer组件显示与隐藏 我们可以根据组件身上的$route获取当前路由的信息&#xff0c;通过路由路径判断Footer显示与隐藏。配置的路由的时候&#xff0c;可以给路由添加路由元信息【meta】&#xff0c;路由需要配置对象&#xff0c;它的key不能瞎写、胡写、乱写 <template&…

Python网络爬虫4-实战爬取pdf

1.需求背景 爬取松产品中心网站下的家电说明书。这里以冰箱为例&#xff1a;松下电器-冰箱网址 网站分析&#xff1a; 第一步&#xff1a; 点击一个具体的冰箱型号&#xff0c;点击了解更多&#xff0c;会打开此型号电器的详情页面。 第二步&#xff1a;在新打开的详情页面中…