DEV Community

HarmonyOS
HarmonyOS

Posted on

How to implement RDB and protect it with encryption?

Read the original article:How to implement RDB and protect it with encryption?

Requirement Description

How to implement RDB and protect it with encryption?

Background Knowledge

A relational database (RDB) store is used to store data in complex relational models, such as the student information including names, student IDs, and scores of each subject, or employee information including names, employee IDs, and positions, based on SQLite. The data is more complex than key-value (KV) pairs due to strict mappings. You can use RelationalStore to implement persistence of this type of data.

Implementation Steps

  • Create an RDB class and implement operations.
  • Create separate classes for each table with the required functions.
  • Initialize RDB in the EntryAbility
  • For encryption, set the encrypt parameter to true while initializing the database.

Code Snippet / Configuration

  • RDB.ets
import { relationalStore } from '@kit.ArkData';

export class Rdb {
  private static _instance: Rdb;

  private constructor() {
  }

  public static get instance(): Rdb {
    if (!this._instance) {
      this._instance = new Rdb();
    }

    return this._instance;
  }

  private _database: relationalStore.RdbStore | null = null;

  async init(context: Context) {
    try {
      const DB_CONFIG: relationalStore.StoreConfig = {
        name: "main.db",
        securityLevel: relationalStore.SecurityLevel.S4,
        encrypt: true
      };

      this._database = await relationalStore.getRdbStore(context, DB_CONFIG);
      console.info('RDB created')

      // create initial tables and set initial data
      if (this._database.version === 0) {
        await this._database.executeSql('create table if not EXISTS table1(id integer PRIMARY KEY, data string);');
        this._database.version = 1;
        console.info('RDB initialized');
      } else {
        console.info('RDB already initialized')
      }
    } catch (e) {
      console.error(`RDB init error, e: ${e.code} ${e}`)
    }
  }

  private _checkDatabase() {
    if (this._database === null) {
      console.error("Database is not initialized. Use 'init()' to initialize the database.")
      return false;
    }
    return true;
  }

  /**
   * insert data
   */
  insert(table: string, data: relationalStore.ValuesBucket | relationalStore.ValuesBucket[]) {
    if (!this._checkDatabase()) {
      return;
    }

    try {
      if (data instanceof Array) {
        this._database!.batchInsertSync(table, data)
      } else {
        this._database!.insertSync(table, data)
      }
    } catch (e) {
      console.error(`${table} insert error, e: ${e.code} ${e}`)
    }
  }

  /**
   * query data
   */
  query(table: string, predicates: relationalStore.RdbPredicates,
    columns?: string[]): relationalStore.ResultSet | undefined {
    if (!this._checkDatabase()) {
      return;
    }

    try {
      let results = this._database!.querySync(predicates, columns)
      return results
    } catch (e) {
      console.error(`${table} query error, e: ${e.code} ${e}`)
      return;
    }
  }

  /**
   * query data with sql
   */
  querySql(table: string, sql: string): relationalStore.ResultSet | undefined {
    if (!this._checkDatabase()) {
      return;
    }

    try {
      let results = this._database!.querySqlSync(sql)
      return results
    } catch (e) {
      console.error(`${table} querySql error, e: ${e.code} ${e}`)
      return;
    }
  }

  /**
   * update data
   */
  update(table: string, predicates: relationalStore.RdbPredicates, values: relationalStore.ValuesBucket) {
    if (!this._checkDatabase()) {
      return;
    }

    try {
      this._database!.updateSync(values, predicates);
    } catch (e) {
      console.error(`${table} update error, e: ${e.code} ${e}`)
    }
  }

  /**
   * delete data
   */
  delete(table: string, predicates: relationalStore.RdbPredicates) {
    if (!this._checkDatabase()) {
      return;
    }

    try {
      this._database!.deleteSync(predicates);
    } catch (e) {
      console.error(`${table} delete error, e: ${e.code} ${e}`)
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Table1.ets
import { relationalStore } from "@kit.ArkData";
import { Rdb } from "../Rdb";

export class Table1 {
  private static tableName = 'table1';

  static add(data: string[]) {
    Rdb.instance.insert(Table1.tableName, data.map((s) => {
      return { data: s } as relationalStore.ValuesBucket
    }));
  }

  static delete(id: number) {
    let pre = new relationalStore.RdbPredicates(Table1.tableName).equalTo('id', id);
    Rdb.instance.delete(Table1.tableName, pre);
  }

  static getAll(): string[] {
    const res = Rdb.instance.query(Table1.tableName, new relationalStore.RdbPredicates(Table1.tableName))
    const data: string[] = []

    if (res && res.goToFirstRow()) {
      do {
        const id = res.getDouble(res.getColumnIndex("id")) // use this if needed
        const s = res.getString(res.getColumnIndex('data'))
        data.push(s)
      } while (res.goToNextRow())
    }

    return data
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Initialize RDB
Rdb.instance.init(this.context).then(() => {
  windowStage.loadContent('pages/Index', (err) => {
    if (err.code) {
      hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
      return;
    }
    hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');

    PersistentStorage.persistProp('onboard', false)
  });
})
Enter fullscreen mode Exit fullscreen mode

Written by Mehmet Karaaslan

Top comments (0)