HarmonyOS NEXT - RelationalStore关系型数据库

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 关系型数据库对应用提供通用的操作接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的数据库特性,包括但不限于事务、索引、视图、触发器、外键、参数化查询和预编译SQL语句。

关系型数据库对应用提供通用的操作接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的数据库特性,包括但不限于事务、索引、视图、触发器、外键、参数化查询和预编译SQL语句。

适用的场景:
存储包含复杂关系数据的场景,比如一个班级的学生信息,需要包括姓名、学号、各科成绩等,又或者公司的雇员信息,需要包括姓名、工号、职位等,由于数据之间有较强的对应关系,复杂程度比键值型数据更高,此时需要使用关系型数据库来持久化保存数据。

约束限制

  • 系统默认日志方式是WAL(Write Ahead Log)模式,系统默认落盘方式是FULL模式。
  • 数据库中有4个读连接和1个写连接,线程获取到空闲读连接时,即可进行读取操作。当没有空闲读连接且有空闲写连接时,会将写连接当做读连接来使用。
  • 为保证数据的准确性,数据库同一时间只能支持一个写操作。
  • 当应用被卸载完成后,设备上的相关数据库文件及临时文件会被自动清除。
  • ArkTS侧支持的基本数据类型:number、string、二进制类型数据、boolean。
  • 为保证插入并读取数据成功,建议一条数据不要超过2M。超出该大小,插入成功,读取失败。

基本概念:
·谓词:数据库中用来代表数据实体的性质、特征或者数据实体之间关系的词项,主要用来定义数据库的操作条件。
·结果集:指用户查询之后的结果集合,可以对数据进行访问。结果集提供了灵活的数据访问方式,可以更方便地拿到用户想要的数据。

代码示例
SQLiteUtil

export default class SQLiteUtil {
   
  static getCreateTableSql(tableName: string, columns: ColumnInfo[]): string {
   
    let sql = `CREATE TABLE IF NOT EXISTS ${
     tableName} (`;
    columns.forEach((element, index) => {
   
      if (index == 0) {
   
        //拼接首个元素,默认为主键
        sql += `${
     element.name} ${
     DataType[element.type]} PRIMARY KEY AUTOINCREMENT,`;
      } else if (index == columns.length - 1) {
   
        //最后一个元素拼接语句
        sql += `${
     element.name} ${
     DataType[element.type]} NOT NULL);`;
      } else {
   
        sql += `${
     element.name} ${
     DataType[element.type]} NOT NULL,`;
      }
    });
    return sql;
  }
}

export interface ColumnInfo {
   
  name: string;
  type: DataType;
}

export enum DataType {
   
  NULL = 'NULL',
  INTEGER = 'INTEGER',
  REAL = 'REAL',
  TEXT = 'TEXT',
  BLOB = 'BLOB'
}
AI 代码解读

RelationalStoreService

import SQLiteUtil, {
    ColumnInfo, DataType } from '../ChicKit/data/SQLiteUtil'
import relationalStore from '@ohos.data.relationalStore'
import {
    common } from '@kit.AbilityKit';
import Logger from '../utils/Logger';
import AppError from '../models/AppError';
import Schedule from '../entities/Schedule';
import {
    BusinessError } from '@kit.BasicServicesKit';
import {
    ValuesBucket, ValueType } from '@ohos.data.ValuesBucket';
import {
    DataModel } from '../ChicKit/data/DataModel';
import Target from '../entities/Target';
import Plan from '../entities/Plan';

const RelationalStoreName = 'shijianxu.db'

export default class RelationalStoreService {
   
  static rdbStore: relationalStore.RdbStore;

  /**
   * 初始化关系型数据库
   * @param context
   */
  static init(context: common.UIAbilityContext) {
   
    // RelationalStore配置
    let storeConfig: relationalStore.StoreConfig = {
   
      // 数据库文件名称
      name: RelationalStoreName,
      //安全等级
      securityLevel: relationalStore.SecurityLevel.S1
    }

    relationalStore.getRdbStore(context, storeConfig, (err, store) => {
   
      if (err) {
   
        Logger.error(`RelationalStoreService init error, error=${
     JSON.stringify(new AppError(err))}`)
        return;
      } else {
   
        RelationalStoreService.rdbStore = store
        RelationalStoreService.createScheduleTable()
        RelationalStoreService.createTargetTable()
        RelationalStoreService.createPlanTable()
      }
    });
  }

  /**
   * 创建schedule表
   */
  static createScheduleTable() {
   
    //表字段
    const columns: ColumnInfo[] = Schedule.getColumns()
    // 获取创建表SQL语句
    const sql = SQLiteUtil.getCreateTableSql(Schedule.TableName, columns)
    // 创建数据表
    RelationalStoreService.rdbStore.executeSql(sql, (err) => {
   
      if (err) {
   
        Logger.error(`RelationalStoreService createScheduleTable error, error=${
     JSON.stringify(new AppError(err))}`)
        return;
      }
    });
  }

  /**
   * 创建target表
   */
  static createTargetTable() {
   
    //表字段
    const columns: ColumnInfo[] = Target.getColumns()
    // 获取创建表SQL语句
    const sql = SQLiteUtil.getCreateTableSql(Target.TableName, columns)
    // 创建数据表
    RelationalStoreService.rdbStore.executeSql(sql, (err) => {
   
      if (err) {
   
        Logger.error(`RelationalStoreService createTargetTable error, error=${
     JSON.stringify(new AppError(err))}`)
        return;
      }
    });
  }

  /**
   * 创建plan表
   */
  static createPlanTable() {
   
    //表字段
    const columns: ColumnInfo[] = Plan.getColumns()
    // 获取创建表SQL语句
    const sql = SQLiteUtil.getCreateTableSql(Plan.TableName, columns)
    // 创建数据表
    RelationalStoreService.rdbStore.executeSql(sql, (err) => {
   
      if (err) {
   
        Logger.error(`RelationalStoreService createPlanTable error, error=${
     JSON.stringify(new AppError(err))}`)
        return;
      }
    });
  }

  /**
   * 插入数据
   * @param tableName
   * @param values
   */
  static insert(tableName: string, values: ValuesBucket) {
   
    RelationalStoreService.rdbStore.insert(tableName, values, (err: BusinessError, rowId: number) => {
   
      if (err) {
   
        Logger.error(`RelationalStoreService insert error, error=${
     JSON.stringify(new AppError(err))}`)
        return;
      } else {
   
        return rowId
      }
    })
  }

  /**
   * 删除
   * @param predicates
   * @returns 删除的条数
   */
  static delete(predicates: relationalStore.RdbPredicates):number{
   
    return RelationalStoreService.rdbStore.deleteSync(predicates)
  }

  /**
   * 更新
   * @param values
   * @param predicates
   * @returns 更新的记录条数
   */
  static update(values: ValuesBucket,predicates: relationalStore.RdbPredicates):number{
   
    let rows: number = RelationalStoreService.rdbStore.updateSync(values, predicates, relationalStore.ConflictResolution.ON_CONFLICT_REPLACE);
    return rows
  }

  static querySync(predicates: relationalStore.RdbPredicates, columns: ColumnInfo[]): DataModel[] {
   
    let dataList: DataModel[] = []
    try {
   
      let columnsStringArray: string[] = []
      columns.forEach(element => {
   
        columnsStringArray.push(element.name)
      });
      const resultSet = RelationalStoreService.rdbStore.querySync(predicates, columnsStringArray)
      resultSet.columnNames
      // resultSet.getColumnName('')
      // resultSet.getValue()

      //循环处理结果,循环条件:当所在行不是最后一行
      while (!resultSet.isAtLastRow) {
   
        //去往下一行
        resultSet.goToNextRow()
        let schedule: DataModel = {
   }
        columns.forEach(element => {
   
          switch (element.type) {
   
            case DataType.INTEGER:
              schedule[element.name] = resultSet.getLong(resultSet.getColumnIndex(element.name))
              break;
            case DataType.REAL:
              schedule[element.name] = resultSet.getDouble(resultSet.getColumnIndex(element.name))
              break;
            case DataType.TEXT:
              schedule[element.name] = resultSet.getString(resultSet.getColumnIndex(element.name))
              break;
            case DataType.BLOB:
              schedule[element.name] = resultSet.getBlob(resultSet.getColumnIndex(element.name))
              break;
          }
        })
        dataList.push(schedule)
      }
    } catch (err) {
   
      Logger.error(`RelationalStoreService querySync error, error=${
     JSON.stringify(new AppError(err))}`)
    }
    return dataList
  }
}
AI 代码解读
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
蓝鹰
+关注
目录
打赏
0
27
27
0
124
分享
相关文章
|
3天前
|
HarmonyOS NEXT - 通用属性
这段代码展示了组件的通用属性设置方法,涵盖尺寸、位置、布局约束、Flex布局、边框、背景及图像效果等多方面。通过TypeScript实现,提供了灵活的样式配置选项。例如,`.size()` 和 `.width()` 用于调整组件尺寸;`.align()` 和 `.position()` 控制对齐与定位;`.border()` 系列方法定义边框样式;`.backgroundColor()` 和 `.backgroundImage()` 设置背景;图像效果如模糊、阴影、灰度等可通过相应方法实现。
54 0
|
3天前
|
HarmonyOS NEXT 通用事件
通用事件涵盖事件分发、触屏事件、键鼠事件、焦点事件和拖拽事件等多种类型。事件分发将用户操作生成的触控事件分配至各组件;触屏事件包括Touch与Mouse类事件;键鼠事件处理外接设备输入;焦点事件涉及焦点获取、失去及焦点链管理;拖拽事件支持数据在组件间传递。 代码示例展示了如何通过`onClick`实现点击计数、`onFocus`与`onBlur`处理焦点事件,以及通过`bindPopup`展示气泡弹窗提示。此外,还提供了输入框的焦点状态管理与验证逻辑,确保用户体验流畅且交互清晰。
53 0
|
3天前
HarmonyOS NEXT - @Prop和@Link
本示例介绍了`@Prop`和`@Link`装饰器在父子组件间的数据同步机制。`@Prop`实现单向数据绑定,子组件可修改本地值,但不会同步回父组件;父组件数据更新时会覆盖子组件的本地更改。`@Link`实现双向绑定,子组件与父组件数据共享且相互影响。 **限制条件:** - `@Prop`变量深拷贝时可能丢失复杂类型。 - `@Link`不可用于`@Entry`组件,禁止本地初始化,类型需与数据源一致。 **支持类型:** - `@Prop`支持基础类型、对象、数组、`Date`及联合类型,不支持`any`。 - 数据源与`@Prop`类型需匹配,包括简单类型、数组项及对象属性。
58 41
|
3天前
|
HarmonyOS NEXT - @Provide和@Consume
@Provide和@Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递。
56 21
HarmonyOS NEXT - Preferences用户首选项
- 用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。 - Preferences会将该数据缓存在内存中,当用户读取的时候,能够快速从内存中获取数据。Preferences会随着存放的数据量越多而导致应用占用的内存越大,因此,Preferences不适合存放过多的数据。
56 19
|
3天前
HarmonyOS NEXT - @State状态变量
ArkUI 是一种声明式 UI 框架,通过状态驱动 UI 更新。@State 装饰的变量用于管理组件内部状态,具有以下特点:私有性(仅组件内访问)、必须初始化、生命周期与组件一致。它支持单向(与 @Prop)和双向(与 @Link、@ObjectLink)数据同步。状态改变时,绑定的 UI 会自动刷新。注意:@State 不支持 Function 类型,不能在 build 中修改状态变量。代码示例中展示了通过 @State 管理按钮点击计数的状态更新机制。
54 16
|
3天前
|
HarmonyOS NEXT - AlertDialog警告弹窗
`AlertDialog` 是一个用于显示警告弹窗的组件,支持自定义文本内容与回调操作。通过 `AlertDialog.show()` 方法,传入配置参数即可展示弹窗。主要功能包括设置标题、内容、按钮、模态状态、对齐方式、过渡动画等。示例代码展示了如何创建一个包含“取消”和“删除”按钮的弹窗,并在点击按钮后执行相应业务逻辑,同时更新页面消息提示。适用于需要用户确认或交互的场景。
51 14
|
3天前
|
HarmonyOS NEXT - @CustomDialog自定义弹窗
CustomDialog 是一个用于实现自定义弹窗的工具,适用于广告、中奖提示、警告信息、软件更新等用户交互场景。通过 `CustomDialogController` 类可控制弹窗的显示与隐藏。开发者可配置多种选项,如对齐方式、偏移量、蒙层颜色、动画效果等,支持模态与非模态窗口,并可通过装饰器 `@CustomDialog` 定义弹窗界面。示例代码展示了如何创建欢迎弹窗及响应用户操作,灵活满足不同需求。
56 13
|
3天前
|
HarmonyOS NEXT - @Builder自定义构建函数
ArkUI 提供了轻量级的 UI 元素复用机制 `@Builder`,用于将重复使用的 UI 元素抽象为可复用组件。它支持两种使用方式:**私有自定义构建函数**和**全局自定义构建函数**。 - **私有构建函数**定义在组件内部,可访问组件状态变量,适用于需要与组件状态交互的场景。 - **全局构建函数**独立于组件,适合无状态变化的复用逻辑。 通过 `@Builder`,开发者可以简化代码结构,提高复用性和可维护性。例如,`this.task('晨跑', true)` 可动态生成任务项。参数传递支持按值和按引用两种方式,需遵循类型一致及不可修改参数值等规则。
55 13
|
3天前
|
HarmonyOS NEXT - @Component自定义组件
在ArkUI中,组件是构成UI的基本单元,分为系统组件和自定义组件。自定义组件通过封装UI与业务逻辑,提升代码复用性和可维护性。其特点包括可组合、可重用及数据驱动UI更新。定义时使用`@Component`装饰器修饰struct,并实现`build()`函数描述UI。可通过`@Entry`标记为页面入口,或用`@Reusable`增强复用能力。成员函数和变量默认私有,状态管理需遵循特定规则。 示例代码展示了通过自定义组件`Home`和`Person`模块化开发UI页面的过程,结合`Tabs`实现多页面切换功能。
54 10