鸿蒙Next relationalStore关系型数据库封装(常用增删改查)

52 阅读2分钟

打个比方,我们有一个书籍管理系统,用数据库存储每一本书籍数据,我们基于此封装一个BooksStoreManager的书籍管理系统。

import { relationalStore } from "@kit.ArkData";
import { BusinessError } from "@kit.BasicServicesKit";

/// 书籍模型
export class BookInfoModel {
    id: number | undefined
    name: string | undefined
    icon: string | undefined
    remark: string | undefined
    chapter: string | undefined
}

/// 书籍管理数据库
export class BooksStoreManager{

    private static instance: BooksStoreManager | null
    private constructor() {}
    static getInstance(): BooksStoreManager {
      if (BooksStoreManager.instance == null) {
        BooksStoreManager.instance =
          AppStorage.get<BooksStoreManager>('BooksStoreManager') as BooksStoreManager;
        if (!BooksStoreManager.instance) {
          BooksStoreManager.instance = new BooksStoreManager();
          AppStorage.setOrCreate('BooksStoreManager', BooksStoreManager.instance);
        }
      }
      return BooksStoreManager.instance
    }

    /// RdbStore对象
    private rdbBookStore?: relationalStore.RdbStore
    /// 表名
    private tableName: string = 'BooksTable'
    /// Rdb数据库配置
    /// name:数据库名称
    /// securityLevel:数据库安全级别
    private readonly BookStoreConfig:relationalStore.StoreConfig = {
      name: "BookListInfo.db",
      securityLevel: relationalStore.SecurityLevel.S1
    }
    /// 数据库创建sql语句(不支持分号分隔的多条语句)
    private sqlCreate: string = `CREATE TABLE IF NOT EXISTS ${this.tableName}(
                    id INTEGER NULL,
                    name TEXT NULL,
                    icon TEXT NULL,
                    remark TEXT NULL,
                    chapter TEXT NULL)`
    /// 数据字段
    private dbColumns:Array<string> = ['id', 'name', 'icon', 'remark', 'chapter']

    /// 初始化任务
    initBookDB(context: Context) {
      relationalStore.getRdbStore(context,this.BookStoreConfig,(err, rdbStore) => {
        if (err) {
          console.log('testTag', '获取rdb失败');
          return
        }
        rdbStore.executeSql(this.sqlCreate)
        /// ....... 或者去创建其他的表
        console.log('创建表成功');
        this.rdbBookStore = rdbStore
      })
    }

    /// 查询所有书籍
    async getBookList(): Promise<BookInfoModel[]> {
      let predicates = new relationalStore.RdbPredicates(this.tableName)
      let result = await this.rdbBookStore?.query(predicates,this.dbColumns)
      let booksList: BookInfoModel[] = []
      while (!result?.isAtLastRow) {
        result?.goToNextRow()
        let bookInfo:BookInfoModel = new BookInfoModel()
        bookInfo.id = result?.getLong(result.getColumnIndex('id'))
        bookInfo.name = result?.getString(result.getColumnIndex('name'))
        bookInfo.icon = result?.getString(result.getColumnIndex('icon'))
        bookInfo.remark = result?.getString(result.getColumnIndex('remark'))
        bookInfo.chapter = result?.getString(result.getColumnIndex('chapter'))
        booksList.push(bookInfo)
      }
      result?.close();// 释放数据集的内存,若不释放可能会引起fd泄露与内存泄露.
      return booksList
    }

    /// 增加一本书籍
    addBookInfo(item: BookInfoModel):Promise<number|void|null> {
      const data: relationalStore.ValuesBucket = {
        id:item.id ?? 0,
        name: item.name ?? '',
        icon: item.icon ?? '',
        remark: item.remark ?? '',
        chapter: item.chapter ?? '',
      };
      if (!this.rdbBookStore){
        return Promise.resolve(null)
      }
      return this.rdbBookStore.insert(this.tableName, data)
        .then(res => res)
        .catch((err: BusinessError) => {
         console.info("bookInfo failed, err: " + err)
      })
    }

    /// 通过id查询并返回一条数据。如果为null,则表示数据库中没有这条数据.
    async findBookById(id: number):Promise<BookInfoModel | null> {
      let predicate = new relationalStore.RdbPredicates(this.tableName)
      predicate.equalTo('id', id) /// 谓词匹配id
      /// 第二个参数this.dbColumns,表示要查询的列.
      let resultSet:relationalStore.ResultSet|undefined = await this.rdbBookStore?.query(predicate, this.dbColumns)
      let bookInfo: BookInfoModel | null = null
      // resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始.
      while (resultSet?.goToNextRow()){
        bookInfo = new BookInfoModel()
        bookInfo.id = resultSet?.getLong(resultSet.getColumnIndex('id'))
        bookInfo.name = resultSet?.getString(resultSet.getColumnIndex('name'))
        bookInfo.icon = resultSet?.getString(resultSet.getColumnIndex('icon'))
        bookInfo.remark = resultSet?.getString(resultSet.getColumnIndex('remark'))
        bookInfo.chapter = resultSet?.getString(resultSet.getColumnIndex('chapter'))
      }
      resultSet?.close();
      return bookInfo
    }

    /// 根据id判断书籍是否存在
    async isBookExists(id: number):Promise<boolean>{
      let predicate = new relationalStore.RdbPredicates(this.tableName)
      predicate.equalTo('id', id)
      let resultSet:relationalStore.ResultSet|undefined =
        await this.rdbBookStore?.query(predicate, this.dbColumns)
      resultSet?.close();
      return resultSet?.goToNextRow() ?? false
    }

    /// 通过id删除某一本书
    deleteBookById(id: number, callback: () => void) {
      let predicate = new relationalStore.RdbPredicates(this.tableName)
      predicate.equalTo('id', id)
      return this.rdbBookStore?.delete(predicate,
        (err: BusinessError, rows: number) => {
        if (err) {
          console.info("Delete failed, err: " + err)
          return
        }
        callback();
      })
    }

    /// 通过书籍id删除某一些书籍
    clearBooksByIds(ids: Array<number>, callback: () => void) {
      let predicate = new relationalStore.RdbPredicates(this.tableName)
      ids.forEach((id: number, index: number) => {
        predicate = predicate.equalTo('id', id)
        if (index < ids.length - 1) {
          predicate = predicate.or() /// 拼接谓词"逻辑或",以便可以匹配多本书籍.
        }
      })
      return this.rdbBookStore?.delete(predicate, (err: BusinessError, rows: number) => {
        if (err) {
          console.info("Clear failed, err: " + err)
          return
        }
        callback();
      })
    }

    /// 更新某本书籍的数据库信息
    updateBookInfoById(id: number, item: BookInfoModel) {
      let predicate = new relationalStore.RdbPredicates(this.tableName)
      predicate.equalTo('id', id) /// 通过id匹配到这本书
      const data: relationalStore.ValuesBucket = {
        id:item.id ?? 0,
        name: item.name ?? '',
        icon: item.icon ?? '',
        remark: item.remark ?? '',
        chapter: item.chapter ?? '',
      };
      return this.rdbBookStore?.update(data, predicate)
    }

}

最后,我们需要在EntryAbility类的onCreate生命周期方法中初始化数据库

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  /// 初始化书籍数据库
  BooksStoreManager.getInstance().initBookDB(this.context)
}