鸿蒙next sqlite进阶版本来了

前言导读

各位网友大家好,有段时间没有更大家见面了,之前我写过一个关于鸿蒙next 里面轻量化数据库的使用,那个过程复杂而且不好使用

今天我就带着大家一起封装一个开箱即用的sqlite 的工具类库 希望后面同学再存储数据的时候不再繁琐。那么废话不多说我们正式开始

效果图

具体实现

1封装我们的 策略接口 基类 BaseStrategy

我们一共定义了 建表 ,初始化数据库 插入数据 查询所有数据 删除数据等方法

ts 复制代码
  /**
   * 策略接口
   */
  export interface BaseStrategy {
    /**
     * 设置数据库SQL参数
     * @param dbName 数据库名称
     * @param tableName 表名
     * @param sqlArgsMap SQL参数映射
     */
    setDbSqlArgs(dbName: string, tableName: string, sqlArgsMap: Map<string, string>): void;
  
    /**
     * 初始化数据库
     */
    initSssDb(context: any): Promise<void>;
  
    /**
     * 获取本地数据库订单信息
     * @returns 订单信息列表
     */
    getLocalDbOrderInfo(): Promise<Array<Map<string, string>>>;
  
    /**
     * 插入或更新子订单
     * @param uniqueKey 唯一标识键
     * @param uniqueValue 唯一标识值
     * @param contentMap 内容映射
     */
    insertOrUpdateSub(uniqueKey: string, uniqueValue: string, contentMap: Map<string, string>): Promise<void>;
  
    /**
     * 删除数据库数据
     * @param uniqueKey 唯一标识键
     * @param uniqueValue 唯一标识值
     */
    deleteDbData(uniqueKey: string, uniqueValue: string): Promise<void>;
  
  
  
  
  }
2 策略实现类
ts 复制代码
  import { LocalSaveHelper } from './helper/LocalSaveHelper';
  import { BaseStrategy } from './inf/BaseStrategy';
  import { DbLog } from './util/DbLog';
  import {SdkRdbHelper} from './db/SdkRdbHelper'
  
  
  /**
   * 策略实现类
   */
  export class MyPayStrategy implements BaseStrategy {
    private static instance: MyPayStrategy | null = null;
  
  
    private constructor() {
  
    }
  
  
  
    /**
     * 获取单例实例
     * @returns MkPaySsStrategy实例
     */
    public static getInstance(): MyPayStrategy {
      if (!MyPayStrategy.instance) {
        MyPayStrategy.instance = new MyPayStrategy();
      }
      return MyPayStrategy.instance;
    }
  
    /**
     * 设置数据库SQL参数
     * @param dbName 数据库名称
     * @param tableName 表名
     * @param args SQL参数映射
     */
    public setDbSqlArgs(dbName: string, tableName: string, args: Map<string, string>): void {
      if (!args) {
        this.printLog('table args is null!!!');
      } else if (args.size <= 0) {
        this.printLog('table args size is empty!!!');
      } else {
        if (!dbName) {
          this.printLog('database name is empty!!!');
        }
        if (!tableName) {
          this.printLog('table name is empty!!!');
        }
        LocalSaveHelper.getInstance().setDbName(dbName);
        LocalSaveHelper.getInstance().setDbTableName(tableName);
        LocalSaveHelper.getInstance().setDbSqlArgsMap(args);
      }
    }
  
    /**
     * 初始化数据库
     */
    public async initSssDb(context:Context): Promise<void> {
      try {
        this.printLog('initSssDb');
        if (!LocalSaveHelper.getInstance().getSqlArgsMap()) {
          this.printErrLog('Please assign an instance first about SqlArgsMap');
        } else {
          await SdkRdbHelper.getInstance().initRdbStore(context);
        }
      } catch (error) {
        DbLog.eWithStack(error.message, error);
      }
    }
  
    /**
     * 获取本地数据库订单信息
     * @returns 订单信息列表
     */
    public async getLocalDbOrderInfo(): Promise<Array<Map<string, string>>> {
      try {
        this.printLog('getLocalDbOrderInfo');
        return await SdkRdbHelper.getInstance().getSdkOrderInfo();
      } catch (error) {
        DbLog.eWithStack(error.message, error);
        return [];
      }
    }
  
    /**
     * 插入或更新子订单
     * @param uniqueKey 唯一标识键
     * @param uniqueValue 唯一标识值
     * @param args 参数映射
     */
    public async insertOrUpdateSub(uniqueKey: string, uniqueValue: string, args: Map<string, string>): Promise<void> {
      try {
        this.printLog('insertOrUpdateSub');
        await SdkRdbHelper.getInstance().insertOrUpdateSub(uniqueKey, uniqueValue, args);
      } catch (error) {
        DbLog.eWithStack(error.message, error);
      }
    }
  
    /**
     * 删除数据库数据
     * @param uniqueKey 唯一标识键
     * @param uniqueValue 唯一标识值
     */
    public async deleteDbData(uniqueKey: string, uniqueValue: string): Promise<void> {
      try {
        this.printLog('deleteDbData');
         SdkRdbHelper.getInstance().deleteDbOrderData(uniqueKey, uniqueValue);
      } catch (error) {
        DbLog.eWithStack(error.message, error);
      }
    }
  
    /**
     * 打印日志
     * @param msg 日志消息
     */
    private printLog(msg: string): void {
      DbLog.d(msg);
    }
  
    /**
     * 打印错误日志
     * @param msg 错误日志消息
     */
    private printErrLog(msg: string): void {
      DbLog.e(msg);
    }
  }
3 获取数据库建表SQL语句
ts 复制代码
/**
 * 获取数据库建表SQL语句
 * @param tableName 表名
 * @returns 建表SQL语句
 */
public static getSssDbSql(tableName: string): string {
  const argsMap = LocalSaveHelper.getInstance().getSqlArgsMap();
  let sql = `CREATE TABLE IF NOT EXISTS ${tableName} (ID INTEGER PRIMARY KEY AUTOINCREMENT`;
  
  if (argsMap) {
    const entries = argsMap.entries();
    for (const entry of entries) {
      const key = entry[0];
      const value = entry[1];
      sql += `, ${key} ${this.getArgsVariable(value)}`;
    }
  }
  
  sql += ');';
  DbLog.d(`sql: ${sql}`);
  return sql;
}
4 SDK关系数据库帮助类
ts 复制代码
import { LocalSaveHelper } from '../helper/LocalSaveHelper';
import { DbLog } from '../util/DbLog';
import { MYPayType } from '../constant/MYPayType';
import { PaySsUtils } from '../util/PaySsUtils';
import { relationalStore } from '@kit.ArkData';


/**
 * SDK关系数据库帮助类
 */
export class SdkRdbHelper {
  public  static instance: SdkRdbHelper|null = null;
  private store: relationalStore.RdbStore | undefined = undefined;

  /**
   * 获取单例实例
   * @returns SdkRdbHelper实例
   */
  public static getInstance(): SdkRdbHelper {
    if (!SdkRdbHelper.instance) {
      SdkRdbHelper.instance = new SdkRdbHelper();
    }
    return SdkRdbHelper.instance;
  }

  /**
   * 初始化数据库
   * @param context 上下文
   */
  public async initRdbStore(context: Context){
    const STORE_CONFIG: relationalStore.StoreConfig = {
      name: 'RdbTest.db', // 数据库文件名
      securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别
      encrypt: false, // 可选参数,指定数据库是否加密,默认不加密
      customDir: 'customDir/subCustomDir', // 可选参数,数据库自定义路径。数据库将在如下的目录结构中被创建:context.databaseDir + '/rdb/' + customDir,其中context.databaseDir是应用沙箱对应的路径,'/rdb/'表示创建的是关系型数据库,customDir表示自定义的路径。当此参数不填时,默认在本应用沙箱目录下创建RdbStore实例。
      isReadOnly: false // 可选参数,指定数据库是否以只读方式打开。该参数默认为false,表示数据库可读可写。该参数为true时,只允许从数据库读取数据,不允许对数据库进行写操作,否则会返回错误码801。
    };
    try {
      // if(this.store){
      // //  this.store = await rdb.getRdbStore(context, this.STORE_CONFIG);
      //   await rdb.getRdbStore(context,this.STORE_CONFIG).then((data)=>{
      //
      //   })
      // }

      // 获得一个相关的RdbStore,操作关系型数据库,用户可以根据自己的需求配置RdbStore的参数,
      // 然后通过RdbStore调用相关接口可以执行相关的数据操作,使用callback异步回调。
      relationalStore.getRdbStore(context, STORE_CONFIG, (err, store) => {
        if (err) {
          console.error(`At LoginPage Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
          return;
        }
        console.info('At LoginPage Succeeded in getting RdbStore.');
        // 当数据库创建时,数据库默认版本为0
        if (store.version === 0) {
          const tableName = LocalSaveHelper.getInstance().getDbTableName();
          const sql = PaySsUtils.getSssDbSql(tableName);
          store.executeSql(sql); // 创建数据表
          // 设置数据库的版本,入参为大于0的整数
          store.version = 1;
        }
        // 赋值给当前的rdbStore对象,确保获取到RdbStore实例后,再进行数据库的增、删、改、查等操作
        this.store = store
      });

    } catch (error) {
      DbLog.e(`初始化数据库失败: ${error.message}`);

    }
  }

  /**
   * 获取SDK订单信息
   * @returns 订单信息列表
   */
  public async getSdkOrderInfo(): Promise<Array<Map<string, string>>> {
    const resultList: Array<Map<string, string>> = [];
    try {
      if (!this.store) {
        DbLog.e('数据库未初始化');
        return resultList;
      }

      const tableName = LocalSaveHelper.getInstance().getDbTableName();
      const resultSet = await this.store.querySql(`SELECT * FROM ${tableName} ORDER BY ID DESC`, []);

      while (resultSet.goToNextRow()) {
        const resultMap = new Map<string, string>();
        const argsMap = LocalSaveHelper.getInstance().getSqlArgsMap();

        if (argsMap) {
          const entries = argsMap.entries();
          for (const entry of entries) {
            const key = entry[0];
            const value = entry[1];
            const columnIndex = resultSet.getColumnIndex(key);
            if (columnIndex !== -1) {
              if (value === MYPayType.TEXT) {
                resultMap.set(key, resultSet.getString(columnIndex));
              } else {
                resultMap.set(key, resultSet.getString(columnIndex));
              }
            }
          }
        }
        resultList.push(resultMap);
      }

      resultSet.close();
    } catch (error) {
      DbLog.e(`查询订单信息失败: ${error.message}`);
    }

    return resultList;
  }

  /**
   * 插入或更新子订单
   * @param uniqueKey 唯一标识键
   * @param uniqueValue 唯一标识值
   * @param contentMap 内容映射
   */
  public async insertOrUpdateSub(uniqueKey: string, uniqueValue: string, contentMap: Map<string, string>): Promise<void> {
    try {
      if (!this.store) {
        DbLog.e('数据库未初始化');
        return;
      }

      const tableName = LocalSaveHelper.getInstance().getDbTableName();
      
      // 检查记录是否存在
      const queryResultSet = await this.store.querySql(
        `SELECT COUNT(*) AS count FROM ${tableName} WHERE ${uniqueKey} = ?`,
        [uniqueValue]
      );

      let exists = false;
      if (queryResultSet.goToNextRow()) {
        const count = queryResultSet.getLong(queryResultSet.getColumnIndex('count'));
        exists = count > 0;
      }
      queryResultSet.close();

      if (exists) {
        // 更新操作
        let updateSql = `UPDATE ${tableName} SET `;
        const values: string[] = [];
        const params: string[] = [];

        const entries = contentMap.entries();
        for (const entry of entries) {
          const key = entry[0];
          const value = entry[1];
          values.push(`${key} = ?`);
          params.push(value);
        }
        updateSql += values.join(', ');
        updateSql += ` WHERE ${uniqueKey} = ?`;
        params.push(uniqueValue);

        await this.store.executeSql(updateSql, params);
        DbLog.d('记录已存在,执行更新操作');
      } else {
        // 插入操作
        let insertSql = `INSERT INTO ${tableName} (`;
        const columns: string[] = [];
        const placeholders: string[] = [];
        const params: string[] = [];

        // 添加唯一键
        columns.push(uniqueKey);
        placeholders.push('?');
        params.push(uniqueValue);

        const entries = contentMap.entries();
        for (const entry of entries) {
          const key = entry[0];
          const value = entry[1];
          columns.push(key);
          placeholders.push('?');
          params.push(value);
        }

        insertSql += columns.join(', ') + ') VALUES (' + placeholders.join(', ') + ')';
        await this.store.executeSql(insertSql, params);
        DbLog.d('执行插入操作');
      }
    } catch (error) {
      DbLog.e(`插入或更新子订单失败: ${error.message}`);
    }
  }

  /**
   * 删除数据库订单数据
   * @param uniqueKey 唯一标识键
   * @param uniqueValue 唯一标识值
   */
  public async deleteDbOrderData(uniqueKey: string, uniqueValue: string): Promise<void> {
    try {
      if (!this.store) {
        DbLog.e('数据库未初始化');
        return;
      }

      const tableName = LocalSaveHelper.getInstance().getDbTableName();
      
      // 检查记录是否存在
      const queryResultSet = await this.store.querySql(
        `SELECT COUNT(*) AS count FROM ${tableName} WHERE ${uniqueKey} = ?`,
        [uniqueValue]
      );

      let exists = false;
      if (queryResultSet.goToNextRow()) {
        const count = queryResultSet.getLong(queryResultSet.getColumnIndex('count'));
        exists = count > 0;
      }
      queryResultSet.close();

      if (exists) {
        const deleteSql = `DELETE FROM ${tableName} WHERE ${uniqueKey} = ?`;
        await this.store.executeSql(deleteSql, [uniqueValue]);
        DbLog.d('删除数据库订单数据成功');
      }
    } catch (error) {
      DbLog.e(`删除数据库订单数据失败: ${error.message}`);
    }
  }

  /**
   * 关闭数据库连接
   */
  public async close(): Promise<void> {
    if (this.store) {
       this.store.close();
    }
  }
}

使用示例

ts 复制代码
import { MYPayType } from "./constant/MYPayType";
import { MyPayStrategy } from "./MyPayStrategy";
import { Context } from "@kit.AbilityKit";
import {UserInfo}  from './model/UserInfo'


/**
 * 使用示例
 */
export class PaySssSdkExample {

  private static instance: PaySssSdkExample | null = null;


  private constructor() {}



  /**
   * 获取单例实例
   * @returns MyPayStrategy实例
   */
  public static getInstance(): PaySssSdkExample {
    if (!PaySssSdkExample.instance) {
      PaySssSdkExample.instance = new PaySssSdkExample();
    }
    return PaySssSdkExample.instance;
  }
  /**
   * 初始化SDK示例
   */
  public async initSdkExample(context: Context): Promise<void> {
    try {
      // 获取SDK实例
      const sdk = MyPayStrategy.getInstance();
      // 设置数据库参数
      const sqlArgs = new Map<string, string>();
      sqlArgs.set('username', MYPayType.TEXT);
      sqlArgs.set('password', MYPayType.TEXT);
      sdk.setDbSqlArgs('user_database', 'username', sqlArgs);
      
      // 初始化数据库
      await sdk.initSssDb(context);
      
      console.log('SDK初始化完成');
    } catch (error) {
      console.error('SDK初始化失败:', error);
    }
  }
  
  /**
   * 插入订单示例
   */
  public async insertOrderExample(userInfo:UserInfo): Promise<void> {
    try {
      const sdk = MyPayStrategy.getInstance();
      // 创建订单数据
      const userData = new Map<string, string>();
      userData.set('username', userInfo.username);
      userData.set('password', userInfo.password);
      // 插入或更新订单
      await sdk.insertOrUpdateSub('username', userInfo.username, userData);
      
      console.log('订单插入成功');
    } catch (error) {
      console.error('订单插入失败:', error);
    }
  }
  
  /**
   * 查询订单示例
   */
  public async queryOrdersExample(): Promise<Array<Map<string, string>>>  {
    try {
      const sdk = MyPayStrategy.getInstance();
      
      // // 获取所有订单信息
      // const orders = await sdk.getLocalDbOrderInfo();
      //
      // console.log('查询到的订单数量:', orders.length);
      // orders.forEach((order, index) => {
      //   console.log(`订单 ${index + 1}:`, order);
      // });

      return await sdk.getLocalDbOrderInfo();
    } catch (error) {
      console.error('查询订单失败:', error);
      return [];
    }
  }
}

我们封装一下 然后再我们的UI组件里面去使用

scss 复制代码
import {PaySssSdkExample} from  '../PaySssSdkExample'
import  {UserInfo}  from '../model/UserInfo'

@Extend(TextInput)function inputStyle(){
  .placeholderColor($r('app.color.placeholder_color'))
  .height(45)
  .fontSize(18)
  .backgroundColor($r('app.color.background'))
  .width('100%')
  .padding({left:0})
  .margin({top:12})
}
@Extend(Line)function lineStyle(){
  .width('100%')
  .height(1)
  .backgroundColor($r('app.color.linecolor'))
  .margin({left:5,right:5})
}

@Extend(Text)function textStyle(){
  .fontColor($r('app.color.black_text_color'))
  .fontSize(18)
  .fontWeight(FontWeight.Medium)
}

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State getid:string='';
  @State username:string='';
  @State password:string='';

  @State datamap:Array<Map<string, string>>=[];

  aboutToAppear(): void {
    PaySssSdkExample.getInstance().initSdkExample(getContext());
  }

  build() {
    RelativeContainer() {
       Column({space:10}){


         Row(){
           Row(){
             Text("username").textStyle()
           }.width(100)
           .height('100%')
           .justifyContent(FlexAlign.Center)

           TextInput({placeholder:"请输入username"})
             .maxLength(20)
             .type(InputType.Normal)
             .inputStyle()
             .onChange((value:string)=>{
               this.username=value;
             }).margin({left:20})
         }.width('100%')
         .height(50)
         .justifyContent(FlexAlign.Start)

         Line().lineStyle()

         Row(){

           Row(){
             Text("password").textStyle()
           }.width(100)
           .height('100%')
           .justifyContent(FlexAlign.Center)

           TextInput({placeholder:"请输入password"})
             .maxLength(20)
             .type(InputType.Normal)
             .inputStyle()
             .onChange((value:string)=>{
               this.password=value;
             }).margin({left:20})
         }.width('100%')
         .height(50)
         .justifyContent(FlexAlign.Start)

         Line().lineStyle()


         Row({space:10}){
           Button("插入数据").onClick(()=>{
            let  userInfo: UserInfo=new UserInfo();
            userInfo.id=this.getid;
            userInfo.username=this.username;
            userInfo.password=this.password;
             PaySssSdkExample.getInstance().insertOrderExample(userInfo);

           }).layoutWeight(1)

           Button("查询数据").onClick(()=>{
             PaySssSdkExample.getInstance().queryOrdersExample().then((data)=>{
               this.datamap=data;
             })
           }).layoutWeight(1)


         }.width("100%").margin({left:20,right:20})

         List({space:10}){
           ForEach(this.datamap,(item:Map<string, string>)=>{
             ListItem(){
               Column(){
                 Text(item?.get("id")).fontSize(18).fontColor(Color.Black)
                   .margin({top:5})
                 Text(item?.get("username")).fontSize(15).fontColor(Color.Gray)
                   .margin({top:5})
                 Text(item?.get("password")).fontSize(15).fontColor(Color.Black)
                   .margin({top:5})
               }.justifyContent(FlexAlign.Start).margin({left:20}).alignItems(HorizontalAlign.Start)

             }.height(100)
             .width('100%')
           })
         }



       }.width("100%")
      .height("100%")
    }
    .height('100%')
    .width('100%')
  }
}

最后总结

我们封装了数据库工具类后 我们对比我们平常要写一堆的建表语句 还有需要编写我们的查询语句 和我们的删除语句 ,我们很好封装和

数据库辅助工具类就可以进减少我们调用者来编写这部分点,当然整个工具类不完善 我们其实可以继续完善 进一步抽象 ,可以·把我们的

model 转成map 这个时候我们只需要操作对象存储和查询获取 还有删除的动作即可,如果觉得文章还不错麻烦给我一键三连谢谢

相关推荐
c***97982 小时前
HarmonyOS在智能车载系统的集成
华为·车载系统·harmonyos
1***s6323 小时前
HarmonyOS智能电视应用开发指南
华为·harmonyos·智能电视
lqj_本人7 小时前
鸿蒙Cordova开发踩坑记录:跨域请求的“隐形墙“
harmonyos
Z***258011 小时前
HarmonyOS在物联网场景的应用
物联网·华为·harmonyos
Pocker_Spades_A13 小时前
John the Ripper 在 HarmonyOS 上的构建与适配
华为·harmonyos
不爱吃糖的程序媛14 小时前
鸿蒙PC Electron 打印服务实现详解
华为·electron·harmonyos
开源头条17 小时前
2025开源鸿蒙开发者激励计划正式启动,为生态繁荣注入持久动力
华为·开源·harmonyos
奔跑的露西ly20 小时前
【HarmonyOS NEXT】自定义样式复用
华为·harmonyos
lqj_本人20 小时前
HarmonyOS + Cordova:打包发布与环境差异常见问题指南
华为·harmonyos