鸿蒙端云一体化开发(二):云数据库

欢迎来到鸿蒙端云一体化开发教程的第二篇。上一篇我们学习了云函数,今天咱们来攻克另一个核心功能------云数据库

在开发应用时,数据存储是绕不开的话题。传统开发需要自己搭建数据库服务器、设计表结构、编写SQL语句,还得操心数据库的备份、扩容和安全问题。Cloud Foundation Kit的云数据库服务把这些麻烦事都解决了。它提供了一个端云协同的数据库,你可以在客户端直接对数据进行增删改查,而且支持数据实时同步,非常适合开发需要跨设备同步数据的应用。

一、实战场景:图书管理系统

为了让大家更好地理解,我们今天通过开发一个简单的"图书管理系统"来学习云数据库的使用。我们需要实现以下功能:

  1. 录入新书信息(写入数据)
  2. 查询书籍列表(查询数据)
  3. 借阅书籍(更新数据)
  4. 图书遗失处理(删除数据)

二、在AGC控制台配置数据库

在写代码之前,我们需要先在云端把"地基"打好。

2.1 新增对象类型

云数据库使用"对象类型"来定义数据结构,有点像传统数据库里的"表"。

  1. 登录AppGallery Connect,进入"云开发 > 云数据库"页面。

  2. 点击"新增",创建一个名为BookInfo的对象类型。

  3. 添加以下字段:

字段名称 类型 主键 非空 说明
id Integer 图书ID
bookName String - 书名
author String - - 作者
price Double - - 价格
borrowerId Integer - - 借阅人ID
borrowerName String - - 借阅人姓名
borrowerTime Date - - 借阅时间
  1. 添加索引:点击"新增索引",设置索引名为bookName,这样按书名查询会更快。

  2. 设置权限:为了演示方便,我们将"所有人"、"认证用户"、"数据创建者"、"管理员"的权限(query, upsert, delete)都勾选上。注意:实际项目中,为了安全起见,建议根据业务严格限制"所有人"的权限。

2.2 导出并引入对象类型文件

配置好后,我们需要把这个定义导出给代码使用。

  1. 在对象类型列表中勾选BookInfo,点击"导出"。

  2. 选择"json格式",下载得到一个文件。

  3. 将文件重命名为schema.json

  4. 在你的DevEco Studio项目中,将该文件拷贝到AppScope/resources/rawfile或者entry/src/main/resources/rawfile目录下。

2.3 新增存储区

存储区就是存放数据的地方,相当于一个具体的数据库实例。

  1. 在云数据库页面点击"存储区"页签。
  2. 点击"新增",输入名称QuickStartDemo,点击确定。

三、代码实现

地基打好了,现在开始盖楼!

3.1 创建数据对象类

我们需要在ArkTS代码中创建一个类来对应云端的BookInfo。新建BookInfo.ets文件:

typescript 复制代码
import { cloudDatabase } from '@kit.CloudFoundationKit';

class BookInfo extends cloudDatabase.DatabaseObject {
  public naturalbase_ClassName(): string {
    return "BookInfo";
  }
  public id: number | undefined;
  public bookName: string | undefined;
  public author: string | undefined;
  public price: number | undefined;
  public borrowerId: number | undefined;
  public borrowerName: string | undefined;
  public borrowerTime: Date | undefined;
}

export { BookInfo };

3.2 初始化云数据库

在使用数据库之前,需要进行初始化。通常我们会在应用启动或者页面加载时做这件事。

首先,别忘了申请网络权限。在entry/src/main/module.json5中添加:

json 复制代码
"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
]

然后,初始化数据库区域(DatabaseZone):

typescript 复制代码
import { cloudDatabase } from '@kit.CloudFoundationKit';
import { BookInfo } from './BookInfo'; // 引入刚才定义的类

// 使用我们在控制台创建的存储区名称 'QuickStartDemo'
let databaseZone = cloudDatabase.zone('QuickStartDemo');

// 创建查询条件对象,后续查询都要用到它
let condition = new cloudDatabase.DatabaseQuery(BookInfo);

3.3 写入数据(新增/修改)

云数据库提供了一个非常方便的方法叫upsert(更新插入)。如果数据不存在(主键ID不同),它就新增;如果数据已存在(主键ID相同),它就更新。

场景一:录入新书

typescript 复制代码
import { hilog } from '@kit.PerformanceAnalysisKit';

async function addBook() {
  try {
    let book = new BookInfo();
    book.id = 1;
    book.bookName = "鸿蒙开发实战";
    book.author = "张三";
    book.price = 59.9;
    
    // 写入数据
    let record = await databaseZone.upsert(book);
    hilog.info(0x0000, 'testTag', `成功录入书籍: ${JSON.stringify(record)}`);
  } catch (err) {
    hilog.error(0x0000, 'testTag', `录入失败: ${err.code}, ${err.message}`);
  }
}

场景二:借阅书籍(更新数据)

借书其实就是更新书籍的借阅人信息。

typescript 复制代码
async function borrowBook() {
  try {
    // 假设我们要借阅《鸿蒙开发实战》
    // 先查询这本书(这里简化逻辑,假设已知ID为1)
    let book = new BookInfo();
    book.id = 1; 
    book.bookName = "鸿蒙开发实战"; // upsert需要主键,其他字段如果要更新也需要赋值
    book.borrowerId = 1001;
    book.borrowerName = "李四";
    book.borrowerTime = new Date();

    // 再次调用upsert,因为ID已存在,会执行更新操作
    let record = await databaseZone.upsert(book);
    hilog.info(0x0000, 'testTag', `借阅成功: ${JSON.stringify(record)}`);
  } catch (err) {
    hilog.error(0x0000, 'testTag', `借阅失败: ${err.code}, ${err.message}`);
  }
}

3.4 查询数据

查询是数据库最常用的功能。云数据库提供了非常丰富的查询能力。

场景三:查询所有书籍

typescript 复制代码
async function queryAllBooks() {
  try {
    // 空的condition表示无过滤条件,查询所有
    let resultArray = await databaseZone.query(condition);
    hilog.info(0x0000, 'testTag', `查询到 ${resultArray.length} 本书`);
  } catch (err) {
    hilog.error(0x0000, 'testTag', `查询失败: ${err.code}, ${err.message}`);
  }
}

场景四:按条件查询(复合查询)

比如我们要找"价格在20到50之间,且书名包含'数据库'"的书:

typescript 复制代码
async function searchBooks() {
  try {
    condition.contains('bookName', '数据库')
      .greaterThan('price', 20.0)
      .and() // 多个条件默认是and,也可以显式调用
      .lessThan('price', 50.0);
      
    let resultArray = await databaseZone.query(condition);
    hilog.info(0x0000, 'testTag', `符合条件的书籍: ${JSON.stringify(resultArray)}`);
  } catch (err) {
    hilog.error(0x0000, 'testTag', `查询失败: ${err.code}, ${err.message}`);
  }
}

场景五:随机推荐(随机查询)

从6.0.1版本开始,支持随机查询,特别适合做"猜你喜欢"功能。

typescript 复制代码
async function recommendBooks() {
  try {
    // 随机取出10本书
    condition.orderByRandom().limit(10);
    let resultArray = await databaseZone.query(condition);
    hilog.info(0x0000, 'testTag', `推荐书籍: ${JSON.stringify(resultArray)}`);
  } catch (err) {
    hilog.error(0x0000, 'testTag', `推荐失败: ${err.code}, ${err.message}`);
  }
}

3.5 删除数据

场景六:图书遗失处理

如果书丢了,需要从系统中删除。

typescript 复制代码
async function deleteBook() {
  try {
    let book = new BookInfo();
    book.id = 1; // 只需要设置主键即可
    
    let deleteNum = await databaseZone.delete(book);
    hilog.info(0x0000, 'testTag', `成功删除 ${deleteNum} 本书`);
  } catch (err) {
    hilog.error(0x0000, 'testTag', `删除失败: ${err.code}, ${err.message}`);
  }
}

四、进阶技巧

4.1 数据排序与分页

当数据量很大时,我们通常需要分页显示。

typescript 复制代码
async function queryByPage() {
  // 查询价格小于50的书,按价格降序排列
  // limit(10, 6) 表示跳过前6条,取接下来的10条(即第2页,每页10条,从第7条开始取)
  condition.lessThan('price', 50.0)
    .orderByDesc('price')
    .limit(10, 6);
    
  let resultArray = await databaseZone.query(condition);
}

4.2 算术计算

如果你想知道所有书的平均价格,不需要把书都查出来再自己算,直接用calculateQuery

typescript 复制代码
async function getAveragePrice() {
  try {
    // 计算所有价格小于50的书的平均价
    condition.lessThan('price', 50.0);
    let resultNum = await databaseZone.calculateQuery(condition, 'price', cloudDatabase.QueryCalculate.AVERAGE);
    hilog.info(0x0000, 'testTag', `平均价格: ${resultNum}`);
  } catch (err) {
    hilog.error(0x0000, 'testTag', `计算失败: ${err.code}, ${err.message}`);
  }
}

五、注意事项

  1. 存储区限制:一个应用最多创建4个存储区,多了会报错。一般情况下一个就够用了。
  2. 批量操作限制:写入或删除一组对象时,单次不能超过1000条,总大小不能超过2MB。
  3. 查询对象databaseZonecondition对象在每次查询中建议独立使用或重置,避免上一次的查询条件影响下一次。
  4. 数据一致性upsertdelete操作是原子性的,要么全成功,要么全失败,这保证了数据的一致性。
  5. 权限控制:在AGC控制台配置权限时要格外小心,正式上线前一定要检查"所有人"角色的权限,防止数据泄露。

六、总结

至此,我们掌握了云数据库的核心用法:

云数据库极大地简化了后端数据存储的开发工作,让你能更专注于前端业务逻辑的实现。下一篇教程,我们将学习如何使用云存储来管理图片、视频等大文件!

相关推荐
小雨青年2 小时前
【鸿蒙原生开发会议随记 Pro】 数据存储架构 RelationalStore 在复杂资产管理中的应用
华为·架构·harmonyos
l1t2 小时前
DeepSeek辅助总结的测试PostgreSQL数据库插入性能方法
数据库·postgresql
赫萝的红苹果2 小时前
实验探究并验证MySQL innoDB中的各种锁机制及作用范围
android·数据库·mysql
霖霖总总3 小时前
[小技巧45]MySQL Undo Log解析:Undo Log分类与存储机制
数据库·mysql
时光慢煮3 小时前
基于 Flutter × OpenHarmony 的文件管家 —— 构建文件类型分类区域
flutter·华为·开源·openharmony
时光慢煮3 小时前
跨端文件管理:Flutter 与 OpenHarmony 搜索栏实战
flutter·华为·开源·openharmony
曾经的三心草3 小时前
Redis-1-基础操作
数据库·redis·缓存
djarmy4 小时前
跨平台Flutter 开源鸿蒙开发指南(三):使用thirdParty的dio库实现网络请求 示例
flutter·华为·harmonyos
电商API&Tina4 小时前
Python请求淘宝商品评论API接口全指南||taobao评论API
java·开发语言·数据库·python·json·php