鸿蒙开发中,数据持久化之Transaction(事务)的概念及应用

SQLite 数据库具备事务处理能力。
事务本质上是一组操作的集合,它具有原子性,意味着这一系列操作要么全部成功执行,要么全部失败,不存在部分操作成功而部分失败的中间状态。

以常见的转账功能为例,A 账户向 B 账户转账一般包含两个独立步骤:先从 A 账户扣除相应金额,再将同等金额存入 B 账户。在没有事务保障的情况下,这两个独立操作可能出现不一致的结果,比如 A 账户扣钱成功,但 B 账户却未收到款项,这种情况会严重影响系统数据的准确性和业务的正常运行。而事务机制就能很好地解决这个问题,当某个操作失败时,它可以将所有操作回滚到初始状态,确保数据的一致性和完整性。

在鸿蒙开发中,rdbStore 提供了 beginTransaction() 和 rollBack() 方法来实现事务,从而保证操作的原子性。下面通过一个具体的代码案例来详细展示如何在鸿蒙中使用事务。

代码案例

  • 配置数据库创建表单
async 复制代码
    // 配置数据库
    const STORE_CONFIG: relationalStore.StoreConfig = {
      name: "RdbTest.db",
      securityLevel: relationalStore.SecurityLevel.S1
    };

    relationalStore.getRdbStore(getContext(), STORE_CONFIG).then(async (rdbStore: relationalStore.RdbStore) => {
      this.rdbStore = rdbStore;
      // 创建表
      rdbStore.executeSql('CREATE TABLE IF NOT EXISTS test_table (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)');

      console.info(TAG, 'Get RdbStore successfully.')
    }).catch((err: BusinessError) => {
      console.error(TAG, `Get RdbStore failed, code is ${err.code},message is ${err.message}`);
    })
  }
  • 开启事务...
typescript 复制代码
  async beginTransaction() {
    try {
      // 开启事务
      (this.rdbStore as relationalStore.RdbStore).beginTransaction();
      //tablename与创建的表单名称一致
      let predicates = new relationalStore.RdbPredicates("test_table");
      predicates.equalTo("name", "harmony");

      (this.rdbStore as relationalStore.RdbStore).delete(predicates, (err, rows) => {
        if (err) {
          console.error(TAG, `Delete failed, code is ${err.code},message is ${err.message}`);
          return;
        }
        (this.rdbStore as relationalStore.RdbStore).commit();
        console.info(TAG, `Delete rows: ${rows}`);
      })

      // 模拟错误情况
      let isError = false; // 可修改为 true 来测试回滚
      if (isError) {
        throw new Error('人为制造异常,中断事务');
      }

      // 执行插入操作
      let valueBucket: relationalStore.ValuesBucket = {
        'id': 1001,
        'name': 'wy'
      };
      (this.rdbStore as relationalStore.RdbStore).insert("test_table", valueBucket).then((rowId: number) => {
        console.info(TAG, `Insert is successful, rowId = ${rowId}`);
        (this.rdbStore as relationalStore.RdbStore).commit()
      }).catch((err: BusinessError) => {
        console.error(TAG, `Insert is failed, code is ${err.code},message is ${err.message}`);
      })
    } catch (e) {
      console.error(TAG, '回滚 rollBack');
      (this.rdbStore as relationalStore.RdbStore).rollBack();
    }
  }

代码解释

  1. 数据库配置与打开:

    • 首先,定义了一个 RdbStoreConfig 对象,用于配置数据库的名称、安全级别和是否加密。
    • 然后,使用 RdbStore.getRdbStore() 方法打开数据库,并在回调函数中创建了一个名为 test_table 的表。
  2. 事务操作:

    • 调用 beginTransaction() 方法开启一个事务。
    • 执行删除操作,将 test_table 表中 name 为 harmony 的记录删除。
    • 通过 isError 变量模拟错误情况,如果 isError 为 true,则抛出一个异常,中断事务的执行。
    • 如果没有异常,执行插入操作,向 test_table 表中插入一条 name 为 wy 的记录。
    • 调用 commit() 方法提交事务。
  3. 异常处理与回滚:

    • 如果在事务执行过程中出现异常,会捕获该异常并在 catch 代码块中调用 rollBack() 方法回滚事务,将数据库状态恢复到事务开始前的状态。

通过这种方式,确保了删除和插入操作要么全部成功,要么全部失败,实现了操作的原子性。

相关推荐
垆边人似月.7 小时前
华为机试题 :两数之和
c++·算法·华为
垆边人似月.7 小时前
华为机试题 :有效的括号
c++·算法·华为
高德开放平台10 小时前
高德开放平台×华为:一句话,开启腕上打车
华为
垆边人似月.10 小时前
华为机试题 :字符串压缩
算法·华为
OH_TPC13 小时前
【鸿蒙优选三方库】@ohos/aki:一行代码让 ArkTS 调 C++
harmonyos
垆边人似月.13 小时前
华为机试题 :最长递增子序列题目
数据结构·c++·算法·华为
wenyiyiyiyiyi14 小时前
我用鸿蒙 ArkTS 写了个自己天天用的备忘录:待办、课表和长期目标,全塞进一块桌面卡片
harmonyos
承渊政道16 小时前
鸿蒙设备远控电脑实测:ToDesk蓝牙键鼠、双模式鼠标、跨端剪贴板,远控电脑更顺手了
计算机外设·电脑·harmonyos·远程工作·todesk
CV工程师丁Sir18 小时前
ArkWeb 手记 04|DevTools 调试与缓存清理
java·spring·缓存·harmonyos
程序猿追1 天前
HarmonyOS 6 上做个极简浏览器:Web 组件 + 前进后退 + 加载进度
前端·华为·harmonyos