import { relationalStore, ValuesBucket,ValueType } from '@kit.ArkData';
import { Context } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { table_schemas } from '../sql/table'

// 数据库配置
const STORE_CONFIG: relationalStore.StoreConfig = {
  // 数据库文件名
  name: 'RdbTest.db',
  // 数据库安全级别
  securityLevel: relationalStore.SecurityLevel.S3,
  // 可选参数,指定数据库是否加密,默认不加密
  encrypt: false,
  // 可选参数,数据库自定义路径。默认在本应用沙箱目录下创建RdbStore实例。
  customDir: 'customDir/subCustomDir',
  // 可选参数,指定数据库是否以只读方式打开。默认为false,表示数据库可读可写。为true时,只允许从数据库读取数据,不允许对数据库进行写操作,否则会返回错误码801。
  isReadOnly: false,
  // 可选参数,指定用户在全文搜索场景(FTS)下使用哪种分词器。默认在FTS下仅支持英文分词,不支持其他语言分词。
  // tokenizer: tokenType
};

/**
 * 关系型数据库工具类
 */
export class RdbStoreUtil {
  private rdbStore: relationalStore.RdbStore | null = null;
  // 静态属性,保存唯一实例
  private static instance: RdbStoreUtil;

  // 私有构造函数,防止外部直接 new RdbStoreUtil()
  private constructor() {
  }

  // 获取单例的静态方法
  public static getInstance(): RdbStoreUtil {
    if (!RdbStoreUtil.instance) {
      RdbStoreUtil.instance = new RdbStoreUtil();
    }
    return RdbStoreUtil.instance;
  }

  async init(context: Context) {
    try {
      console.log('开始初始化数据库...');
      // 1. 获取RdbStore实例
      this.rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
      console.log(`this.rdbStore===${this.rdbStore}`)
      console.log('RdbStore实例获取成功:', !!this.rdbStore);
      if (!this.rdbStore) {
        return;
      }
      // 2. 创建所有表结构(使用事务保证原子性)
      await this.rdbStore.beginTransaction();
      console.log('事务开始成功');
      for (const sql of table_schemas) {
        console.log('执行SQL:', sql);
        await this.executeSql(sql);
        console.log('SQL执行成功');
      }
      await this.rdbStore.commit();
      console.log('事务提交成功');
      console.info('All tables created successfully');
    } catch (error) {
      console.error(`初始化失败: ${JSON.stringify(error)}`);
      // throw error;
      if (error instanceof Error) {
        throw error;
      } else {
        throw new Error('Batch insert failed: ' + String(error));
      }
    }
  }

  /**
   * 执行SQL语句
   */
  private async executeSql(sql: string, params: ValueType[] = []): Promise<void> {
    if (!this.rdbStore) {
      throw new Error('RdbStore not initialized');
    }

    return new Promise((resolve, reject) => {
      this.rdbStore!.executeSql(sql, params, (err: BusinessError) => {
        if (err) {
          console.error(`SQL error: ${sql}`, err);
          reject(err);
        } else {
          resolve();
        }
      });
    });
  }

  /**
   * 通用插入方法
   * @param tableName 表名
   * @param data 要插入的数据对象
   * @returns 插入的行ID
   */
  async insert<T extends Record<string, ValueType>>(
    tableName: string,
    data: T
  ): Promise<number> {
    return new Promise((resolve, reject) => {
      if (!this.rdbStore) {
        reject(new Error('RdbStore未初始化'));
        return;
      }

      // 自动过滤undefined值
      const valueBucket: ValuesBucket = {};
      Object.keys(data).forEach(key => {
        if (data[key] !== undefined) {
          valueBucket[key] = data[key];
        }
      });
      console.log(`valueBucket===${JSON.stringify(valueBucket)}`)
      this.rdbStore.insert(
        tableName,
        valueBucket,
        (err: BusinessError, rowId: number) => {
          if (err) {
            console.error(`插入到 ${tableName} 失败`, err);
            reject(err);
          } else {
            console.log(`插入 ${tableName}, 行ID: ${rowId}`);
            resolve(rowId);
          }
        }
      );
    });
  }

  /**
   * 通用批量插入方法
   * @param tableName 表名
   * @param dataArray 要插入的数据数组
   * @returns 插入的行数
   */
  async batchInsert<T extends Record<string, ValueType>>(
    tableName: string,
    dataArray: T[]
  ): Promise<number> {
    if (!this.rdbStore) {
      throw new Error('RdbStore not initialized');
    }

    await this.rdbStore.beginTransaction();
    let successCount = 0;

    try {
      for (const data of dataArray) {
        await this.insert(tableName, data);
        successCount++;
      }
      await this.rdbStore.commit();
      return successCount;
    } catch (error) {
      // await this.rdbStore.rollback();
      // throw error;
      await this.rdbStore.rollback(1);
      if (error instanceof Error) {
        throw error;
      } else {
        throw new Error('Batch insert failed: ' + String(error));
      }
    }
  }

  /**
   * 通用查询方法
   * @param tableName 表名
   * @param columns 要查询的列(可选,默认查询所有列)
   * @param whereClause WHERE条件(可选)
   * @param whereArgs WHERE参数(可选)
   * @returns 查询结果数组
   */
  async query<T extends Record<string, relationalStore.ValueType>>(
    tableName: string,
    columns?: string[],
    whereClause?: string,
    whereArgs?: relationalStore.ValueType[]
  ): Promise<T[]> {
    return new Promise((resolve, reject) => {
      if (!this.rdbStore) {
        reject(new Error('RdbStore not initialized'));
        return;
      }

      const cols = columns?.length ? columns.join(', ') : '*';
      let sql = `SELECT ${cols} FROM ${tableName}`;
      if (whereClause) {
        sql += ` WHERE ${whereClause}`;
      }
      console.log(`sql====${sql}`)
      console.log(`whereArgs===${JSON.stringify(whereArgs)}`)
      this.rdbStore.querySql(
        sql,
        whereArgs || [],
        (err: BusinessError, resultSet: relationalStore.ResultSet) => {
          if (err) {
            reject(err);
            return;
          }
          console.log(`resultSet===${JSON.stringify(resultSet)}`)
          try {
            const results: T[] = [];
            const columnCount = resultSet.columnCount;

            while (resultSet.goToNextRow()) {
              const row: Record<string, relationalStore.ValueType> = {};
              for (let i = 0; i < columnCount; i++) {
                const columnName = resultSet.getColumnName(i);
                row[columnName] = resultSet.getValue(i);
              }
              results.push(row as T);
            }

            resultSet.close();
            resolve(results);
          } catch (e) {
            resultSet.close();
            reject(e);
          }
        }
      );
    });
  }

  /**
   * 使用RdbPredicates查询
   * @param predicates 查询条件
   * @returns 查询结果数组
   */
  async queryWithPredicates<T extends Record<string, relationalStore.ValueType>>(
    predicates: relationalStore.RdbPredicates
  ): Promise<T[]> {
    return new Promise((resolve, reject) => {
      if (!this.rdbStore) {
        reject(new Error('RdbStore not initialized'));
        return;
      }

      this.rdbStore.query(
        predicates,
        (err: BusinessError, resultSet: relationalStore.ResultSet) => {
          if (err) {
            reject(err);
            return;
          }

          try {
            const results: T[] = [];
            const columnCount = resultSet.columnCount;

            while (resultSet.goToNextRow()) {
              const row: Record<string, relationalStore.ValueType> = {};
              for (let i = 0; i < columnCount; i++) {
                const columnName = resultSet.getColumnName(i);
                row[columnName] = resultSet.getValue(i);
              }
              results.push(row as T);
            }

            resultSet.close();
            resolve(results);
          } catch (e) {
            resultSet.close();
            reject(e);
          }
        }
      );
    });
  }

  /**
   * 通用更新方法
   * @param tableName 表名
   * @param values 要更新的值
   * @param whereClause WHERE条件
   * @param whereArgs WHERE参数
   * @returns 影响的行数
   */
  async update(
    tableName: string,
    values: ValuesBucket,
    whereClause: string,
    whereArgs: ValueType
  ): Promise<number> {
    return new Promise((resolve, reject) => {
      if (!this.rdbStore) {
        reject(new Error('RdbStore not initialized'));
        return;
      }

      const predicates = new relationalStore.RdbPredicates(tableName);
      predicates.equalTo(whereClause, whereArgs);

      this.rdbStore.update(
        values,
        predicates,
        (err: BusinessError, rowsAffected: number) => {
          if (err) {
            reject(err);
          } else {
            resolve(rowsAffected);
          }
        }
      );
    });
  }

  /**
   * 通用删除方法
   * @param tableName 表名
   * @param whereClause WHERE条件
   * @param whereArgs WHERE参数
   * @returns 删除的行数
   */
  async delete(
    tableName: string,
    whereClause: string,
    whereArgs: ValueType
  ): Promise<number> {
    return new Promise((resolve, reject) => {
      if (!this.rdbStore) {
        reject(new Error('RdbStore not initialized'));
        return;
      }

      const predicates = new relationalStore.RdbPredicates(tableName);
      predicates.equalTo(whereClause, whereArgs);

      this.rdbStore.delete(
        predicates,
        (err: BusinessError, rowsAffected: number) => {
          if (err) {
            reject(err);
          } else {
            resolve(rowsAffected);
          }
        }
      );
    });
  }
}

// 单例导出
export const rdbStoreUtil = RdbStoreUtil.getInstance();

使用

import { relationalStore, ValuesBucket, ValueType } from '@kit.ArkData';
import { Context } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { rdbStoreUtil } from './RdbStoreUtil';

// 1. 定义数据接口
interface User extends Record<string, ValueType> {
  // id?: number;  // number 是 ValueType 的子类型
  name: string; // string 是 ValueType 的子类型
  age: number;
  email: string;
}

interface Product extends Record<string, ValueType> {
  // id?: number;
  name: string;
  price: number;
  stock: number;
}

// onWindowStageCreate(windowStage: window.WindowStage): void {
// rdbStoreUtil.init(this.context)
// }

export class RdbStoreUtilExample {
  async example(context:Context) {
    // 2. 初始化数据库
    await rdbStoreUtil.init(context);

    // 3. 插入用户数据
    const userId = await rdbStoreUtil.insert<User>('users', {
      name: '张三',
      age: 30,
      email: 'zhangsan@example.com'
    });

    // 4. 插入产品数据
    const productId = await rdbStoreUtil.insert<Product>('products', {
      name: '智能手机',
      price: 3999,
      stock: 100
    });

    // 5. 查询所有用户
    const allUsers = await rdbStoreUtil.query<User>('users');

    // 6. 条件查询
    const adultUsers = await rdbStoreUtil.query<User>(
      'users',
      ['id', 'name', 'email'],
      'age >= ?',
      [18]
    );

    // 7. 使用RdbPredicates查询
    const predicates = new relationalStore.RdbPredicates('users');
    predicates.equalTo('name', '张三');
    const zhangSan = await rdbStoreUtil.queryWithPredicates<User>(predicates);

    // 8. 更新数据
    await rdbStoreUtil.update(
      'users',
      { age: 31 },
      'id',
      1
    );

    // 9. 删除数据
    await rdbStoreUtil.delete(
      'products',
      'id',
      1
    );

    // 10. 批量插入
    const newUsers:User[] = [
      { name: '李四', age: 25, email: 'lisi@example.com' },
      { name: '王五', age: 28, email: 'wangwu@example.com' }
    ];
    await rdbStoreUtil.batchInsert<User>('users', newUsers);
  }
}

// 单例导出
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐