SkillAgentSearch skills...

RdbPlus

哈啰出行SQLite的ORM框架,无需编写sql代码,通过装饰器解析表结构,一行搞定增删改查

Install / Use

/learn @yongoe1024/RdbPlus
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

rdb-plus 使用文档

简介

SQLite的ORM框架,无需编写sql代码,通过装饰器解析表结构,一行搞定增删改查

使用API5.0.0(12)编译,已在哈啰出行一汽奥迪等APP中使用

QQ交流群:1056151906

版本说明(使用方法与文档有较大变化)

v3.1.2

  1. 新增Wrapper支持传入条件,控制是否应用这条语句。例:eq('name', '张三', 判断条件)
  2. 增删改操作现在具有返回值,详情可查看函数说明

v3.1.1

  1. 优化了初始化方法与失败提示
  2. 更新REAMDE中案例,所有操作都用try-catch捕获异常信息
  3. 增加了版本管理version、备份数据库、还原数据库、删除数据库、获取原生store等函数
  4. 查询结果为实体类的实例
  5. @TableField可指定表的字段名。如果不设置,将使用实体类中的字段名作为数据库表的主键字段名。

下载安装

  1. 安装最新版 ohpm i rdbplus
  2. 升级版本 ohpm update rdbplus,建议使用最新版避免bug

OpenHarmony ohpm 环境配置等更多内容,请参考如何安装 OpenHarmony ohpm 包

工程版本升级教程

使用案例

https://gitee.com/yongoe/RdbPlus/tree/main/entry/src/main/ets

https://github.com/yongoe1024/RdbPlus/tree/main/entry/src/main/ets

功能介绍

| 函数名 | 介绍 | |----------------|-----------------------| | count | 查询符合条件的记录总数 | | getList | 查询符合条件的记录 | | getPage | 分页查询符合条件的记录 | | getOne | 查询第一个符合条件的记录 | | getObject | 查询符合条件的记录,返回对象数组 | | getObjectBySql | 输入SQL查询符合条件的记录,返回对象数组 | | getById | 根据主键查询 | | insert | 插入一条记录 | | insertBatch | 插入多条记录 | | updateById | 根据主键更新数据 | | update | 更新符合条件的记录 | | deleteById | 根据主键删除 | | delete | 删除符合条件的记录 |

引入教程

  1. 首先引入ohpm依赖:ohpm i rdbplus
  2. EntryAbilityonCreate 中调用 Connection.init() 进行初始化
  3. 创建一个数据库表对应的ets类,并用装饰器@Table@TableField标注
  4. 调用BaseMapper.build()构造实例
  5. 在页面调用实例,使用增删改查的方法,无需编写SQL代码

初始化

EntryAbility调用 Connection.init() 进行初始化

传入两个参数:Context、日志DbLogger(可空),不需要日志可以不传

注:rdbplus提供了DbLogger,可以自行继承Logger接口构造日志对象

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { Connection, DbLogger } from 'rdbplus';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    Connection.init(this.context, new DbLogger())
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    windowStage.loadContent('pages/Index', (err) => {

    });
  }
}

第一步:创建实体类

  1. 创建Employee.ets,字段名要与数据库字段一一对应
  2. 数据库没有的字段,不需要标注@TableField
  3. 当数据库表中有字段,而class没有,不影响结果,数据库返回的结果,都可以正常从返回结果中取出来
  4. 数据表字段类型与class字段类型不一致,不影响结果,ets的类型仅在编译期限制(建议类型保持一致)
import { Table, TableField, FieldType } from "rdbplus"

@Table({ tableName: 't_emp' })
export class Employee {
  /**
   * id,数据库字段为id
   */
  @TableField({ name: 'id', type: FieldType.NUMBER, isPrimaryKey: true })
  id?: number
  /**
   * 名字,数据库字段为name,同名可省略TableField.name
   */
  @TableField({ type: FieldType.TEXT, })
  name?: string
  /**
   * 年龄,数据库字段为age,myAge与数据库字段age互相映射
   */
  @TableField({ name: 'age', type: FieldType.NUMBER, })
  myAge?: number

  /**
   * 其他字段,会被sql忽略,不参与操作
   */
  other?: number
}

第二步:创建Mapper类

  1. 创建static变量 private static mapper: BaseMapper<Employee>
  2. 使用 BaseMapper.build()创建实例,参数分别为实体类数据库配置
import { relationalStore } from '@kit.ArkData'
import { BaseMapper } from 'rdbplus'
import { Employee } from './Employee'

export class EmpMapper {
  private static mapper: BaseMapper<Employee>

  // 单例模式
  static getInstance() {
    if (!EmpMapper.mapper) {
      EmpMapper.mapper = BaseMapper.build<Employee>({
        class: Employee,
        config: {
          name: 'RdbTest.db', // 数据库文件名
          securityLevel: relationalStore.SecurityLevel.S3, // 数据库安全级别
          encrypt: false, // 可选参数,指定数据库是否加密,默认不加密
          customDir: 'customDir/subCustomDir', // 可选参数,数据库自定义路径。
          isReadOnly: false // 可选参数,是否以只读方式打开。默认为false
        }
      })
    }
    return EmpMapper.mapper
  }
}

第三步:页面中调用

@Entry
@Component
struct Index {
  mapper = EmpMapper.getInstance()

  build() {
    Column() {
      Button('count').onClick(async () => {
        try {
          // 入参可空,即不构造条件查询
          let num = await this.mapper.count(new Wrapper())
          showDialog(num + '')
        } catch (e) {
          console.error(e)
        }
      })
    }
  }
}

创建表、数据库版本管理、复杂SQL

  1. 调用EmpMapper对象中的getConnection()方法,得到一个Connection对象
  2. execDML执行创建、添加、修改语句,execDQL执行查询语句
console.log('删除数据库')
Connection.deleteRdbStore('RdbTest.db')
/**
 * 创建表
 * 修改表结构需要控制版本
 * 修改后数据库版本增加,且无法降低版本
 */
function createTable() {
  let db: Connection | undefined = undefined
  try {
    db = await EmpMapper.getInstance().getConnection()
    console.log('createTable 首次打开 版本 0');
    // 初始默认 0
    if (db.version === 0) {
      await db.execDML(
        `create table if not exists "t_emp" (
              id integer primary key autoincrement,
              name varchar(20)
          )`, [])
      db.version = 1
      console.log('createTable 创建表后 版本 1')
    }
    if (db.version === 1) {
      // 添加字段
      db.execDML('ALTER TABLE t_emp ADD COLUMN  age integer');
      db.version = 2;
      console.log('createTable 修改后 版本 2')
    }
    if (db.version === 2) {
      // 以此类推
      console.log('createTable 最终版本 2')
    }
  } catch (e) {
    console.error(e)
  } finally {
    db?.close()
  }
}

装饰器介绍

Table

用于指定实体类对应的数据库表名

| 入参 | 说明 | |-------------------|-------| | tableName: string | 数据库表名 |

TableField

用于标记实体类中的字段

| 入参 | 说明 | |------------------------|--------| | name?: string | 数据库字段名 | | type: FieldType | 字段类型 | | isPrimaryKey?: boolean | 是否主键 |

API介绍

count

查询符合条件的记录总数

| 入参 | 说明 | |-------------------|-------| | wrapper?: Wrapper | 条件构造器 |

| 返回值 | 说明 | |--------|-----| | number | 统计值 |

try {
  let num = await this.mapper.count(new Wrapper())
} catch (e) {
  console.error(e)
}

getObject

查询符合条件的记录,返回一个对象

| 入参 | 说明 | |-------------------|-------| | wrapper?: Wrapper | 条件构造器 |

| 返回值 | 说明 | |------------|------| | EsObject[] | 对象数组 |

try {
  const res: ESObject = await this.mapper.getObject(new Wrapper().eq('name', '123'))
} catch (e) {
  console.error(e)
}

getObjectBySql

传入SQL,查询符合条件的记录,返回对象数组

| 入参 | 说明 | |-------------------------------------|-------| | sql: string | sql语句 | | params: relationalStore.ValueType[] | 占位符参数 |

| 返回值 | 说明 | |------------|------| | EsObject[] | 对象数组 |

try {
  const res: ESObject = await this.mapper.getObjectBySql('select count(*) from t_emp where age = ? ', [13])
} catch (e) {
  console.error(e)
}

getList

查询符合条件的记录,返回对象数组

| 入参 | 说明 | |-------------------|-------| | wrapper?: Wrapper | 条件构造器 |

| 返回值 | 说明 | |-----|------| | T[] | 对象数组 |

try {
  const res = await this.mapper.getList(new Wrapper().eq('name', '123'))
} catch (e) {
  console.error(e)
}

getOne

查询符合条件的第一条数据

| 入参 | 说明 | |-------------------|-------| | wrapper?: Wrapper | 条件构造器 |

| 返回值 | 说明 | |-----|------| | T | 实体对象 |

try {
  const res = await this.mapper.getOne(new Wrapper().eq('name', '123'))
} catch (e) {
  console.error(e)
}

getPage

分页查询符合条件的记录,返回分页结果

| 入参 | 说明 | |-------------------|-------| | current: number | 查询页数 | | size: number | 每页数量 | | wrapper?: Wrapper | 条件构造器 |

| 返回值 | 说明 | |---------|--------| | Page<T> | 分页查询结果 |

| Page | 说明 | |---------|------| | total | 总数 | | current | 当前页 | | size | 每页数量 | | record | 结果集 |

try {
  // 查询第一页的数据,返回Page对象
  const page = await this.mapper.getPage(1, 10)
  // 总数
  const total = page.total
  // 当前页
  const current = page.current
  // 每页条数
  const size = page.size
  // 结果集
  const record = page.record
} catch (e) {
  console.error(e)
}

getById

根据主键查询,返回一个实体对象

| 入参 | 说明 | |---------------|-----| | id: ValueType | 主键值 |

| 返回值 | 说明 | |---------------|-------------------------| | T 或 undefined | 存在返回实体对象,不存在返回undefined |

try {
  const res = await this.mapper.getById(3)
} catch (e) {
  
View on GitHub
GitHub Stars20
CategoryData
Updated1mo ago
Forks3

Languages

TypeScript

Security Score

95/100

Audited on Jan 28, 2026

No findings