<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

HarmonyOS開發案例:【搭建關系型數據庫】(4)

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-05-11 10:27 ? 次閱讀

本節將介紹如何調用關系型數據庫接口在本地搭建數據庫,并讀寫相應的用戶數據。

創建數據庫

要使用關系型數據庫存儲用戶數據,首先要進行數據庫的創建,并提供基本的增、刪、查、改接口。

導入關系型數據庫模塊:

import data_rdb from '@ohos.data.rdb';

開發前請熟悉鴻蒙開發指導文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]
關系型數據庫提供以下兩個基本功能:

獲取RdbStore

首先要獲取一個RdbStore來操作關系型數據庫,代碼如下:

// RdbHelperImp.ets
getRdb(context: Context): Promise< RdbHelper > {
  this.storeConfig = {
    name: this.mDatabaseName, securityLevel: dataRdb.SecurityLevel.S1
  };
  return new Promise< RdbHelper >((success, error) = > {
    dataRdb.getRdbStore(context, this.storeConfig).then(dbStore = > {
      this.rdbStore = dbStore;
      success(this);
    }).catch((err: Error) = > {
      Logger.error(`initRdb err : ${JSON.stringify(err)}`);
      error(err);
    })
  })
}

封裝增、刪、改、查接口

關系型數據庫接口提供的增、刪、改、查操作均有callback和Promise兩種異步回調方式,本Codelab使用了callback異步回調,其中插入數據使用了insert()接口,實現代碼如下:

// RdbHelperImp.ets
insert(tableName: string, values: dataRdb.ValuesBucket | Array< dataRdb.ValuesBucket >): Promise< number > {
  return new Promise< number >((success, error) = > {
    Logger.info(`insert tableName : ${tableName}, values : ${JSON.stringify(values)}`);
    if (!values) {
      Logger.info(`insert failed, values is undefined`);
      error(0);
      return;
    }
    if (values instanceof Array) {
      Logger.info(`insert values isArray = ${values.length}`);
      this.rdbStore.beginTransaction();
      this.saveArray(tableName, values).then(data = > {
        Logger.info(`insert success, data : ${JSON.stringify(data)}`);
        success(data);
        this.rdbStore.commit();
      }).catch((err: Error) = > {
        Logger.error(`insert failed, err : ${err}`);
        error(err);
        this.rdbStore.commit();
      })
    } else {
      this.rdbStore.insert(tableName, values).then(data = > {
        Logger.info(`insert success id : ${data}`);
        success(data);
        his.rdbStore.commit();
      }).catch((err: Error) = > {
        Logger.error(`insert failed, err : ${JSON.stringify(err)}`);
        error(err);
        this.rdbStore.commit();
      })
    }
  })
}

刪除數據使用了delete()接口,實現代碼如下:

// RdbHelperImp.ets
delete(rdbPredicates: dataRdb.RdbPredicates): Promise< number > {
  Logger.info(`delete rdbPredicates : ${JSON.stringify(rdbPredicates)}`);
  return this.rdbStore.delete(rdbPredicates);
}

更新數據使用了update()接口,實現代碼如下:

// RdbHelperImp.ets
update(values: dataRdb.ValuesBucket, rdbPredicates: dataRdb.RdbPredicates): Promise< number > {
  return this.rdbStore.update(values, rdbPredicates);
}

查找數據使用了query()接口,實現代碼如下:

// RdbHelperImp.ets
query(rdbPredicates: dataRdb.RdbPredicates, columns?: Array< string >): Promise< dataRdb.ResultSet > {
  Logger.info(`query rdbPredicates : ${JSON.stringify(rdbPredicates)}`);
  return this.rdbStore.query(rdbPredicates, columns);
}

數據庫表結構

根據健康生活APP的使用場景和業務邏輯,定義了三個數據對象,并使用三張數據表來存儲,分別是健康任務信息表、每日信息表和全局信息表。

健康任務信息表

目前健康生活應用提供了6個基本的健康任務,分別是早起、喝水、吃蘋果、每日微笑、睡前刷牙和早睡。用戶可以選擇開啟或關閉某個任務,開啟的任務可以選擇是否開啟提醒,在指定的時間段內提醒用戶進行打卡。任務也可以選擇開啟的頻率,如只在周一到周五開啟等。需要記錄每項任務的目標值和實際完成值,在用戶打卡后判斷任務是否已經完成,并記錄在數據庫中。因此,需要創建一張存儲每天的健康任務信息的表,表頭如下:

每日信息表

在主頁面,用戶可以查看當天健康任務的完成進度,需要創建一張表記錄當天開啟的任務個數和已經完成的任務個數,表頭如下:

全局信息表

用戶連續多日打卡完成所有創建的任務可以獲得相應的成就,因此,需要有一張表記錄連續打卡天數和已達成的成就項。另外,考慮應用多日未打開的情況,需要記錄應用第一次打開的日期和最后一次打開的日期以向數據庫回填數據,表頭如下:

創建數據表

根據6.2中設計的表結構,創建對應的數據表,實現對相應數據的讀寫操作。

健康任務信息數據表

在獲取RdbStore后,需要使用executeSql接口執行SQL語句來創建相應的表結構和初始化數據,SQL語句如下:

CREATE TABLE IF NOT EXISTS taskInfo(
  id INTEGER PRIMARY KEY AUTOINCREMENT, 
  date TEXT NOT NULL, 
  taskID INTEGER, 
  targetValue TEXT NOT NULL, 
  isAlarm BOOLEAN, 
  startTime TEXT NOT NULL, 
  endTime TEXT NOT NULL, 
  frequency TEXT NOT NULL, 
  isDone BOOLEAN, 
  finValue TEXT NOT NULL, 
  isOpen BOOLEAN
)

健康任務信息數據表需要提供插入數據的接口,以在用戶當天第一次打開應用時創建當天的健康任務信息,實現代碼如下:

// TaskInfoApi.ets
insertData(taskInfo: TaskInfo, callback: Function): void {
  // 根據輸入數據創建待插入的數據行
  const valueBucket = generateBucket(taskInfo);
  RdbUtils.insert('taskInfo', valueBucket).then(result = > {
    callback(result);
  });
  Logger.info('TaskInfoTable', `Insert taskInfo {${taskInfo.date}:${taskInfo.taskID}} finished.`);
}

其中generateBucket()代碼如下:

// TaskInfoApi.ets
function generateBucket(taskInfo: TaskInfo): dataRdb.ValuesBucket {
  let valueBucket = {} as dataRdb.ValuesBucket;
  Const.TASK_INFO.columns?.forEach((item: string) = > {
    if (item !== 'id') {
      switch (item) {
        case 'date':
          valueBucket[item] = taskInfo.date;
          break;
        case 'taskID':
          valueBucket[item] = taskInfo.taskID;
          break;
        case 'targetValue':
          valueBucket[item] = taskInfo.targetValue;
          break;
        case 'isAlarm':
          valueBucket[item] = taskInfo.isAlarm;
          break;
        case 'startTime':
          valueBucket[item] = taskInfo.startTime;
          break;
        case 'endTime':
          valueBucket[item] = taskInfo.endTime;
          break;
        case 'frequency':
          valueBucket[item] = taskInfo.frequency;
          break;
        case 'isDone':
          valueBucket[item] = taskInfo.isDone;
          break;
        case 'finValue':
          valueBucket[item] = taskInfo.finValue;
          break;
        case 'isOpen':
          valueBucket[item] = taskInfo.isOpen;
          break;
        default:
          break;
      }
    }
  });
  return valueBucket;
}

用戶開啟和關閉任務,改變任務的目標值、提醒時間、頻率等,用戶打卡后修改任務的實際完成值都是通過更新數據接口來實現的,代碼如下:

// TaskInfoApi.ets
updateDataByDate(taskInfo: TaskInfo, callback: Function): void {
  const valueBucket = generateBucket(taskInfo);
  let tableName = Const.TASK_INFO.tableName;
  if (!tableName) {
    return;
  }
  let predicates = new dataRdb.RdbPredicates(tableName);
  // 根據date和taskID匹配要更新的數據行
  predicates.equalTo('date', taskInfo.date).and().equalTo('taskID', taskInfo.taskID);
  RdbUtils.update(valueBucket, predicates).then((result: number) = > {
    callback(result);
  });
  Logger.info('TaskInfoTable', `Update data {${taskInfo.date}:${taskInfo.taskID}} finished.`);
}

用戶可以查看當天和以前某日的健康任務信息,需要提供查找數據接口,實現代碼如下:

// TaskInfoApi.ets
query(date: string, isOpen: boolean = true, callback: Function): void {
  let tableName = Const.TASK_INFO.tableName;
  if (!tableName) {
    return;
  }
  let predicates = new dataRdb.RdbPredicates(tableName);
  predicates.equalTo('date', date);
  // 如果isOpen為true,則只查找開啟的任務 
  if (isOpen) {
    predicates.equalTo('isOpen', true);
  }
  predicates.orderByAsc('taskID');  // 查找結果按taskID排序
  RdbUtils.query(predicates).then(resultSet = > {
    let count = resultSet.rowCount;
    // 查找結果為空則返回空數組,否則返回查找結果數組
    if (count === 0 || typeof count === 'string') {
      Logger.error('TaskInfoTable', `${date} query no results!`);
      const result: TaskInfo[] = [];
      callback(result);
    } else {
      resultSet.goToFirstRow();
      const result: TaskInfo[] = [];
      for (let i = 0; i < count; i++) {
        let tmp = new TaskInfo(0, '', 0, '', false, '', '', '', false, '');
        tmp.isOpen = resultSet.getDouble(resultSet.getColumnIndex('isOpen')) ? true : false;
        tmp.id = resultSet.getDouble(resultSet.getColumnIndex('id'));
        tmp.date = resultSet.getString(resultSet.getColumnIndex('date'));
        tmp.taskID = resultSet.getDouble(resultSet.getColumnIndex('taskID'));
        tmp.targetValue = resultSet.getString(resultSet.getColumnIndex('targetValue'));
        tmp.isAlarm = resultSet.getDouble(resultSet.getColumnIndex('isAlarm')) ? true : false;
        tmp.startTime = resultSet.getString(resultSet.getColumnIndex('startTime'));
        tmp.endTime = resultSet.getString(resultSet.getColumnIndex('endTime'));
        tmp.frequency = resultSet.getString(resultSet.getColumnIndex('frequency'));
        tmp.isDone = resultSet.getDouble(resultSet.getColumnIndex('isDone')) ? true : false;
        tmp.finValue = resultSet.getString(resultSet.getColumnIndex('finValue'));
        result[i] = tmp;
        resultSet.goToNextRow();
      }
      callback(result);
    }
  });
}

每日信息數據表

創建每日信息數據表的SQL語句如下:

CREATE TABLE IF NOT EXISTS dayInfo(
  date TEXT NOT NULL PRIMARY KEY, 
  targetTaskNum INTEGER, 
  finTaskNum INTEGER
)

在當天第一次打開應用時需要初始化每日信息數據,頁面需要根據用戶編輯任務和打卡的情況來更新當天目標任務個數和完成任務個數,所以需要提供插入數據和更新數據的接口,寫法與上一條中相應接口類似,不再贅述。

頁面需要查找對應日期的目標任務個數和完成任務個數用以在頁面顯示任務進度,因此需要查找數據的接口。且頁面在打開時需要顯示當周每天任務的完成情況,因此需要允許一次調用查找一周的每日任務信息。實現代碼如下:

// DayInfoApi.ets
queryList(dates: string[], callback: Function): void {
  let predicates: dataRdb.RdbPredicates = new dataRdb.RdbPredicates(Const.DAY_INFO.tableName ? Const.DAY_INFO.tableName : '');
  predicates.in('date', dates);  // 匹配日期數組內的所有日期
  RdbUtils.query(predicates).then(resultSet = > {
    let count = resultSet.rowCount;
    if (count === 0) {
      Logger.info('DayInfoTable', 'query no results.');
      let result: DayInfo[] = [];
      callback(result);
    } else {
      resultSet.goToFirstRow();
      let result: DayInfo[] = [];
      for (let i = 0; i < count; i++) {
        let tmp = new DayInfo('', 0, 0);
        tmp.date = resultSet.getString(resultSet.getColumnIndex('date'));
        tmp.targetTaskNum = resultSet.getDouble(resultSet.getColumnIndex('targetTaskNum'));
        tmp.finTaskNum = resultSet.getDouble(resultSet.getColumnIndex('finTaskNum'));
        result[i] = tmp;
        resultSet.goToNextRow();
      }
      callback(result);
    }
  });
}

全局信息數據表

創建全局信息數據表的SQL語句如下:

CREATE TABLE IF NOT EXISTS globalInfo(
  id INTEGER PRIMARY KEY, 
  firstDate TEXT NOT NULL, 
  lastDate TEXT NOT NULL, 
  checkInDays INTEGER, achievements TEXT NOT NULL
)

全局信息數據表同樣需要提供插入數據、更新數據和查找數據的接口,寫法與本節前兩條中相應接口類似,不再贅述。
HarmonyOSOpenHarmony鴻蒙文檔籽料:mau123789是v直接拿

搜狗高速瀏覽器截圖20240326151450.png

數據庫初始化

應用首次打開時,數據庫中沒有數據,要做數據庫的初始化,寫入一組空數據。另外,如果用戶連續幾天沒有打開APP,再次打開時需要將數據回寫至數據庫。因此需要實現一個數據庫接口,在應用打開時調用,進行上述操作。代碼如下:

// DatabaseModel.ets
query(date: string, callback: Function) {
  let result: TaskInfo[] = [];
  let self = this;
  GlobalInfoApi.query((globalResult: GlobalInfo) = > {
    if (!globalResult.firstDate) { // 如果找不到全局信息,則寫入
      let globalInfo: GlobalInfo = new GlobalInfo(date, date, 0, '');
      GlobalInfoApi.insertData(globalInfo, (isDone: number) = > {
        if (isDone) {
          Logger.info('AppStart', 'Insert globalInfo success: ' + JSON.stringify(globalInfo));
        }
      });
      self.insertGlobalTask();
      let dayInfo: DayInfo = new DayInfo(date, 0, 0);
      DayInfoApi.insertData(dayInfo, (isDone: number) = > {
        if (isDone) {
          Logger.info('AppStart', 'Insert dayInfo success: ' + JSON.stringify(dayInfo));
        }
      })
      self.insertTask(date);
      callback(result, dayInfo);
    } else { // 如果找到全局信息,則查詢當天的任務信息
      let newGlobalInfo = globalResult;
      let preDate = globalResult.lastDate;
      newGlobalInfo.lastDate = date;
      GlobalInfoApi.updateData(newGlobalInfo, (isDone: number) = > {
        if (isDone) {
          Logger.info('AppStart', 'update globalInfo success: ' + JSON.stringify(newGlobalInfo));
        }
      });
      self.queryPreInfo(date, preDate, result, callback);
    }
  });
}

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據庫
    +關注

    關注

    7

    文章

    3606

    瀏覽量

    63487
  • 鴻蒙
    +關注

    關注

    55

    文章

    1777

    瀏覽量

    42157
  • HarmonyOS
    +關注

    關注

    79

    文章

    1882

    瀏覽量

    29343
收藏 人收藏

    評論

    相關推薦

    HarmonyOS開發案例:【關系數據庫

    使用關系數據庫的相關接口實現了對賬單的增、刪、改、查操作。
    的頭像 發表于 04-22 14:58 ?417次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發案</b>例:【<b class='flag-5'>關系</b>型<b class='flag-5'>數據庫</b>】

    數據庫連接

    在利用 LabVIEW數據庫工具包操作數據庫之前,需要先連接數據庫,這就像操作文件之前,先要打開文件一樣。在這里我們利用UDL連接數據庫。Microsoft設計的ODBC標準只能訪問
    發表于 06-29 21:29

    建立與數據庫的連接

    在利用 LabVIEW數據庫工具包操作數據庫之前,需要先連接數據庫,這就像操作文件之前,先要打開文件一樣。在這里我們利用UDL連接數據庫。Microsoft設計的ODBC標準只能訪問
    發表于 07-01 21:24

    Android如何使用Db4o數據庫

    數據庫的出現是為了更好的適合面向對象方式開發應用程序,因為傳統的關系數據庫與OO模 具有“阻
    發表于 05-24 07:32

    使用NoSQL數據庫的原因

    阻抗失衡 關系模型和內存中的數據結構不匹配 采用更為方便的數據交互方式提升開發效率待處理的數據量很大
    發表于 05-27 06:43

    關系數據庫與非關系數據庫的區別淺析

    關系數據庫的一個劣勢就是 阻抗失諧(impedance mismatch):關系模型和內存中的數據結構之間存在差異
    發表于 06-03 06:03

    HarmonyOS應用開發數據交互--關系數據庫完整流程練習

    名稱使用默認配置創建數據庫配置。 private RdbStore rdbStore;//提供管理關系數據庫 (RDB) 的方法。 //RdbOpenCallback 管理數據庫創建、升級和降級
    發表于 09-13 15:05

    基于Data Ability的關系數據庫數據管理能力,實現數據庫相關應用服務的快速開發

    1. 基于Data Ability的關系數據庫操作方法介紹HarmonyOS支持應用以Ability為單位進行部署,Ability可以分為FA(Feature Ability)和PA
    發表于 09-26 16:43

    一款基于Java實現的小巧而強大的關系數據庫

    H2 是一款基于 Java 實現的小巧而強大的關系數據庫,支持嵌入式、客戶端/服務器以及混合部署模式。H2 數據庫適合嵌入小型應用程序、元數據
    發表于 10-27 06:12

    HarmonyOS數據庫的相關資料下載

    、HarmonyOS數據庫篇之RDB關系數據庫3、HarmonyOS
    發表于 03-28 11:13

    HarmonyOS關系數據庫和對象關系數據庫的使用方法

    extends OrmDatabase { }2.表:被開發者用@Entity注解的實體類,且繼承了OrmObject的類,對應關系數據庫中的表。// 定義了一個實體類User.j
    發表于 03-29 14:10

    請問HarmonyOS是如何解決數據存儲問題的?

    背景描述:現在任何一款成熟的APP應用,如淘寶,將海量信息均是存儲在遠端服務器上,前端(如:web端、手機APP端)通過調用接口來展示商品數據。而在HarmonyOS提供的文檔中:不管是關系
    發表于 03-31 15:31

    求助,Android和HarmonyOS都使用SQLite數據庫,能在兩個環境組合訪問數據庫嗎?

    開發一個APP,同時支持Android和HarmonyOS;Android 和HarmonyOS 都使用SQLite 數據庫,能在兩個環境組合訪問
    發表于 06-17 09:39

    如何在HarmonyOS數據庫進行備份,恢復與加密

    數據庫恢復至可用狀態。 鍵值數據庫關系數據庫均支持對
    發表于 11-07 08:57

    數據庫設計開發案例教程之數據庫設計的資料介紹

    本文檔的主要內容詳細介紹的是數據庫設計開發案例教程之數據庫設計的資料介紹主要內容包括了:1 數據庫設計概述,2 需求分析,3 概念結構設計,4 邏輯結構設計,5
    發表于 01-11 11:20 ?17次下載
    <b class='flag-5'>數據庫</b>設計<b class='flag-5'>開發案</b>例教程之<b class='flag-5'>數據庫</b>設計的資料介紹
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>