鸿蒙关系型数据库简易封装

128 阅读3分钟

今天在工作中遇到了数据的持久化存储操作,由于甲方老大需要使用到关系型数据库的处理,在尝试了一系列的第三方库无果后,最终还是想着尝试一下原生写法,经过一番周折,算是实现了简易的增删查改基础操作。特此留作纪念。

1、数据库的基础配置 + rdbStore实例的获取

// 初始化数据库 + 建表
initDB(context: common.UIAbilityContext, sql: string, dbName: string) {
  const STORE_CONFIG: relationalStore.StoreConfig = {
    name: dbName, // 数据库文件名
    securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别
    encrypt: false, // 可选参数,指定数据库是否加密,默认不加密
  };
  relationalStore.getRdbStore(context, STORE_CONFIG, (error, store) => {
    if (this.rdbStore !== undefined) {
      // this.rdbStore.executeSync(sql) // 创建数据库表
      this.getCreateTable(sql)  // 创建数据库表
      return;
    }
    this.rdbStore = store
    // this.rdbStore.executeSync(sql) // 创建数据库表
    this.getCreateTable(sql) // 创建数据库表
  })
}

此处我希望的是通过传入自定义的SQL语句 + 数据库名称来实现rdbStore实例的获取以及在成功获取之后进行数据库表的创建。 由于实例我个人觉得应该在app启动就先储备好,所以我将此方法在EntryAbility的onCreate生命周期中执行。

2、创建数据库表

// 创建数据库表
getCreateTable(sql:Array<string> | string) {
  // 如果 sql 是字符串,直接执行
  if (typeof sql === 'string') {
    this.rdbStore?.executeSync(sql);
  }
  // 如果 sql 是数组,遍历每个项并执行
  else if (Array.isArray(sql)) {
    sql.forEach((item) => {
      this.rdbStore?.executeSync(item);
    });
  }
}

此处我个人考虑的是在业务场景中可能需要同时创建一张或者多张表,所以我创建方法允许了string + string数组的两种传入方式。

3、数据添加

getAdd(valueBucket: relationalStore.ValuesBucket, tableName: string) {
  if (this.rdbStore != undefined) {
    try {
      (this.rdbStore as relationalStore.RdbStore).insertSync(tableName, valueBucket,
        relationalStore.ConflictResolution.ON_CONFLICT_REPLACE);
    } catch (error) {
      console.error(`Insert is failed, code is ${error.code},message is ${error.message}`);
    }
  }
}

此处再添加数据时,由于我目前还没发现使用对象进行操作,所以只使用了官方目前的valueBucket对象来进行传值,具体使用小伙伴可以直接看看官网,也很简洁明了。

4、数据删除

getDelete(predicates: relationalStore.RdbPredicates) {
  if (this.rdbStore) {
    try {
      let rows: Number = (this.rdbStore as relationalStore.RdbStore).deleteSync(predicates)
    } catch (err) {
      console.error(`Delete failed, code is ${err.code},message is ${err.message}`);
    }
  }
}

此处需要注意的是在方法中删除数据需要的传值是删除条件,predicates是一个 relationalStore.RdbPredicates的对象,如果小伙伴需要全部数据删除,只需要获取到数据库表的名字,不再需要 equalTo()方法去进行具体的参数匹配。反之,小伙伴需要精确删除,自需要equalTo()方法来进行精准匹配。具体使用小伙伴可以查看官方文档。

5、数据修改

// 修改
getUpdate(valueBucket: relationalStore.ValuesBucket, predicates: relationalStore.RdbPredicates) {
  if (this.rdbStore != undefined) {
    try {
      let rows: Number = (this.rdbStore as relationalStore.RdbStore).updateSync(valueBucket, predicates,
        relationalStore.ConflictResolution.ON_CONFLICT_REPLACE);
    } catch (error) {
      console.error(`Updated failed, code is ${error.code},message is ${error.message}`);
    }
  }
}

数据修改方法其实和上述的精确删除大同小异,都是需要equalTo()来进行精准值匹配,然后通过传入的valueBucket对象来进行数据的替换操作

6、数据查询

// 查询--全部查询
getQueryAll(predicates: relationalStore.RdbPredicates, columns?: Array<string>) {
  if (this.rdbStore) {
    try {
      let resultSet: relationalStore.ResultSet =
        (this.rdbStore as relationalStore.RdbStore).querySync(predicates, columns);
      // resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始。
      while (resultSet.goToNextRow()) {
        // const name = resultSet.getString(resultSet.getColumnIndex("NAME"));
        // const age = resultSet.getString(resultSet.getColumnIndex("AGE"));
        // const gender = resultSet.getString(resultSet.getColumnIndex("GENDER"));
        // const des = resultSet.getString(resultSet.getColumnIndex("DES"));
        // console.info(`cxc-- name=${name}, age=${age}, gender=${gender},des=${des}`);
      }
      // 释放数据集的内存,若不释放可能会引起fd泄露与内存泄露
      resultSet.close();
    } catch (err) {
      console.error(`cxc--Query failed, code is ${err.code},message is ${err.message}`);
    }
  }
}

在进行数据查询的时候涉及到全部查询以及精准查询,此操作实则和删除操作一致。 动手试试吧。

Author--小鲤鱼炖豆腐 Time--2025/1/1