【鸿蒙优选三方库】@ohos/dataorm:注解定义实体,告别手写 SQL

手写 SQL 的痛:建表语句拼字符串、JOIN 查询拼字符串、结果集手动映射成对象、字段改名要全局搜替换。@ohos/dataorm 用注解定义实体,链式 API 拼查询,字段名写错编译期就报错。

📦 仓库地址 | ohpm install @ohos/dataorm | v2.3.10-rc.1 | Apache-2.0


它解决什么问题

鸿蒙做本地持久化通常用关系型数据库(RDB)。但直接用原生 RDB Store:

  • 建表、查询、更新全是 SQL 字符串拼接,易错难维护
  • 表结构变更要手动写迁移
  • 实体 ↔ 数据库映射全部手写
  • 一对多、多对一关联查询写起来痛苦
  • 批量操作没有统一封装

@ohos/dataorm 把 Java 圈最成熟的 greenDAO 思路搬进 ArkTS:注解声明模型 → 生成 Dao → 链式 API 查询,还内置迁移、监听、缓存、批量操作工具。


核心能力

能力说明
注解式实体@Entity @Id @NotNull @Unique @Index
完整关联@ToMany @ToOne @JoinEntity @OrderBy
类型转换@Convert 自定义类型 ↔ 数据库值
嵌套对象@Embedded @Transient @Union
链式查询.where().eq().and().like().orderDesc().list()
QueryBuilder 高级去重、JOIN、分页、计数、排序
数据库迁移Migration API 平滑升级表结构
数据监听表/库级变更回调
多数据库单应用多个独立库并存
Async/Sync统一命名后缀,约定清晰

30 秒上手

import { Entity, Id, NotNull, Column, ToMany, List } from '@ohos/dataorm'

@Entity({ tableName: 'NOTE' })
export class Note {
  @Id() @Column({ columnName: 'ID' }) id: number = 0
  @NotNull() @Column({ columnName: 'TEXT' }) text: string = ''
  @Column({ columnName: 'DATE' }) date: number = 0
}
import { DataORM } from '@ohos/dataorm'

const db = DataORM.init({ name: 'app.db', version: 1, entities: [Note] })
const noteDao = db.dao(Note)

// 增
const note = new Note()
note.text = 'Hello HarmonyOS'
note.date = Date.now()
await noteDao.insert(note)

// 查(链式,类型安全)
const list = await noteDao.queryBuilder()
  .where(Note.TEXT.like('%Hello%'))
  .orderDesc(Note.DATE)
  .list()

// 改
note.text = 'Updated'
await noteDao.update(note)

// 删
await noteDao.deleteById(note.id)

关联查询——@ToMany 让关联对象自动带出,不用手写 JOIN:

@Entity({ tableName: 'USER' })
class User {
  @Id() @Column({ columnName: 'ID' }) id: number = 0
  @Column({ columnName: 'NAME' }) name: string = ''
  @ToMany({ joinEntity: Order.class }) orders: List<Order> = new List()
}

// 查用户时订单自动带出
const user = await userDao.queryBuilder().where(User.ID.eq(1)).unique()
console.info(user.orders.length)   // 无需第二次查询

社区已解决的典型问题

异步批量插入大数据量时 await 不等待(#301)
saveInTxAsync 在数据量大时 await 无法同步等待,代码继续往下跑但插入还没完成——后续查询查不到全部数据。Issue 已由维护者处理。业务侧对大批量插入仍建议分批 + 回查校验,分批还能顺带做进度反馈。

数据库升级接口不能回滚(#302)
升级时接口内部捕获了异常,导致事务不能回滚,数据库卡在损坏的中间状态:表结构改了一半,老数据读不出、新数据写不进。已修正异常传播与回滚逻辑。业务侧仍应自己做「备份 → 迁移 → 失败恢复」三步保护。

复合主键示例有误导性(#305 / #307)
Demo 中 CompositePrimaryKey.ets 与 UnionPrimaryKey.ets 的文件名、按钮文案与实际功能存在歧义。已修正。学复合主键用法时以 API.md 官方文档为准,Demo 需交叉验证。

Query 测试用例不足(#298)
社区已补充查询场景的测试覆盖。复杂查询(JOIN、分页、去重)建议在自己项目里先小范围验证行为符合预期。


两个必须遵守的实践

1. 迁移脚本三条铁律

原则说明
幂等可重复执行不出错(用 IF NOT EXISTS)
只增不减新增字段安全,删字段/删表要极度谨慎
可回滚迁移前必备份,失败能恢复

2. 高频查询字段加索引

@Index() @Column({ columnName: 'USER_ID' }) userId: number = 0

数据量小的时候感觉不到差别,积累到几万条后没索引的查询会明显变慢。


适合谁用

  • 本地数据存储:用户信息、设置、配置、缓存
  • 业务实体持久化:订单、商品、文章、聊天记录、打卡记录
  • 复杂关联模型:一对多、多对一、多对多
  • 需要版本迁移:迭代时表结构平滑升级
  • 需要监听变化:跨页面/跨组件响应数据变更
  • 想少写 SQL:代码量减少一个数量级

297 个 Issue 已关闭。数据库是最不能出错的一层——丢一次数据,用户就再也不回来了。这个库的 Issue 列表里,事务和迁移相关的讨论特别值得读一遍。

Logo

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

更多推荐