27 RdbPredicates 条件查询详解:EqualTo、OrderBy、组合条件 27 RdbPredicates 条件查询详解EqualTo、OrderBy、组合条件前言图27 RdbPredicates 条件查询详解EqualTo、OrderBy、组合条件 运行效果截图HarmonyOS NEXT在鸿蒙 RDB 中RdbPredicates是构建数据库查询条件的核心类。它提供了一套链式调用 API让开发者无需编写原始 SQL 即可完成复杂的条件组合。与直接拼接 SQL 相比RdbPredicates更安全、更可读、更易维护。本文以鹿鹿·笔迹心理分析项目中的 UserDao、HandwritingDao、ArchiveDao 等 DAO 代码为例全面解析 RdbPredicates 的各种条件构建方法。鸿蒙官方·RdbPredicates 文档developer.huawei.com项目源码仓库harmony-app GitHub图RdbPredicates 链式 API 分类——等值、范围、模糊、排序、分页RdbPredicates等值条件equalTo / notEqualTo范围条件greaterThan / lessThan / between模糊条件like / glob空值条件isNull / isNotNull排序分组orderByAsc / orderByDesc / groupBy分页限制limit / offset组合条件and / or / beginWrap / endWrap一、RdbPredicates 基础1.1 创建和基本用法RdbPredicates的构造函数接受一个参数——表名表示该谓词适用于哪张表importrelationalStorefromohos.data.relationalStore// 创建 predicates指定表名constpredicatesnewrelationalStore.RdbPredicates(handwriting)1.2 完整查询模式conststoreDatabaseService.getInstance().getStore()constpredicatesnewrelationalStore.RdbPredicates(TABLE)// ... 添加查询条件 ...constrsawaitstore.query(predicates,[col1,col2,...])二、常用查询条件2.1 等值查询// 最简单的等值条件predicates.equalTo(archive_id,archiveId)// SQL 等价WHERE archive_id ?predicates.equalTo(open_id,local)// SQL 等价WHERE open_id ?2.2 排序// 降序排列最新在前predicates.orderByDesc(created_at)// SQL 等价ORDER BY created_at DESC// 升序排列predicates.orderByAsc(created_at)// SQL 等价ORDER BY created_at ASC// 多字段排序predicates.orderByDesc(last_record_at)predicates.orderByDesc(id)// SQL 等价ORDER BY last_record_at DESC, id DESC2.3 区间查询// 不在 NULL 范围内的值predicates.isNotNull(archive_id)// SQL 等价WHERE archive_id IS NOT NULL// NULL 值predicates.isNull(archive_id)// SQL 等价WHERE archive_id IS NULL// 大于predicates.greaterThan(energy_score,50)// SQL 等价WHERE energy_score ?// 小于predicates.lessThan(word_count,100)// SQL 等价WHERE word_count ?// 范围predicates.between(created_at,startTime,endTime)// SQL 等价WHERE created_at BETWEEN ? AND ?// INpredicates.in(source,[camera,gallery])// SQL 等价WHERE source IN (?, ?)提示所有值都是参数化绑定?占位符不存在 SQL 注入风险。三、链式调用3.1 连续的链式调用// ArchiveDao.listByUserconstpredicatesnewrelationalStore.RdbPredicates(TABLE).equalTo(user_id,userId).orderByDesc(last_record_at)// SQL 等价WHERE user_id ? ORDER BY last_record_at DESC3.2 分步链式调用// HandwritingDao.listUnclassifiedconstpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.beginWrap()predicates.equalTo(archive_id,0)predicates.or()predicates.isNull(archive_id)predicates.endWrap()predicates.orderByDesc(created_at)// SQL 等价WHERE (archive_id 0 OR archive_id IS NULL) ORDER BY created_at DESC四、组合条件beginWrap / or / endWrap4.1 OR 组合// 查询未归类笔迹archive_id 0 或 archive_id IS NULLconstpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.beginWrap()predicates.equalTo(archive_id,0)// 条件 Apredicates.or()// ORpredicates.isNull(archive_id)// 条件 Bpredicates.endWrap()predicates.orderByDesc(created_at)// SQL 等价// WHERE (archive_id 0 OR archive_id IS NULL)// ORDER BY created_at DESC4.2 AND 组合默认行为如果不显式添加or()多个条件默认以AND连接constpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.equalTo(archive_id,archiveId)// 默认 ANDpredicates.orderByDesc(created_at)// SQL 等价WHERE archive_id ? ORDER BY created_at DESC// 实际上只有 1 个 WHERE 条件 1 个 ORDER BY4.3 嵌套条件// 复杂场景示例constpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.equalTo(user_id,userId)// user_id ?predicates.beginWrap()// (predicates.greaterThan(energy_score,60)// energy_score ?predicates.or()// ORpredicates.in(source,[camera,handwrite])// source IN (?, ?)predicates.endWrap()// )// SQL 等价// WHERE user_id ?// AND (energy_score ? OR source IN (?, ?))五、各 DAO 中的 RdbPredicates 应用汇总5.1 UserDao// findByOpenId —— 等值查询 单条结果constpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.equalTo(open_id,openId)// updateName —— 等值条件 updateconstpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.equalTo(id,id)awaitstore.update({name},predicates)5.2 HandwritingDao// findById —— 等值查询predicates.equalTo(id,id)// listByArchive —— 等值 排序predicates.equalTo(archive_id,archiveId)predicates.orderByDesc(created_at)// listUnclassified —— 组合条件ORpredicates.beginWrap()predicates.equalTo(archive_id,0)predicates.or()predicates.isNull(archive_id)predicates.endWrap()predicates.orderByDesc(created_at)// batchUpdateArchive —— 循环更新for(constidofids){constpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.equalTo(id,id)awaitstore.update({archive_id:archiveId},predicates)}5.3 ArchiveDao// listByUser —— 等值 排序predicates.equalTo(user_id,userId)predicates.orderByDesc(last_record_at)// findById —— 等值查询predicates.equalTo(id,id)// delete —— 等值条件删除predicates.equalTo(id,id)awaitstore.delete(predicates)5.4 各 DAO 的 RdbPredicates 使用统计DAOequalToorderByDescbeginWrap/or/endWrap用途UserDao✅❌❌用户查询HandwritingDao✅✅✅笔迹多条件查询ArchiveDao✅✅❌档案查询ReportDao✅✅❌报告查询RelationDao✅✅❌关系查询六、RdbPredicates vs 原始 SQL6.1 对比对比维度RdbPredicates原始 SQLquerySql类型安全✅ 方法名明确语义❌ 字符串拼接易错SQL 注入防护✅ 自动参数化绑定❌ 需手动?占位可读性✅ 链式调用清晰⚠️ 字符串较长时可读性差复杂查询JOIN❌ 不支持✅ 完全支持聚合函数❌ 不支持✅ COUNT / AVG / GROUP BY参数绑定自动需手动传 bindArgs6.2 选择建议// ✅ 用 RdbPredicates简单条件查询constpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.equalTo(archive_id,archiveId)predicates.orderByDesc(created_at)awaitstore.query(predicates,COLS)// ✅ 用原始 SQL聚合统计awaitstore.querySql(SELECT COUNT(*) AS cnt FROM handwriting WHERE archive_id ?,[archiveId])七、RdbPredicates 的完整 API方法用途SQL 等价项目中是否使用equalTo(field, value)等于WHERE field ?✅notEqualTo(field, value)不等于WHERE field ! ?❌greaterThan(field, value)大于WHERE field ?❌lessThan(field, value)小于WHERE field ?❌between(field, lo, hi)范围WHERE field BETWEEN ? AND ?❌in(field, values)INWHERE field IN (?, ?)❌notIn(field, values)NOT INWHERE field NOT IN (?, ?)❌isNull(field)为空WHERE field IS NULL✅isNotNull(field)非空WHERE field IS NOT NULL❌like(field, pattern)模糊WHERE field LIKE ?❌orderByAsc(field)升序ORDER BY field ASC❌orderByDesc(field)降序ORDER BY field DESC✅limit(count)限制行数LIMIT ?❌用 querySql 替代beginWrap()左括号(✅endWrap()右括号)✅or()OROR✅提示项目中主要使用equalTo、orderByDesc、beginWrap/or/endWrap这几种就覆盖了 90% 的查询场景。更复杂的统计查询直接使用原始 SQL。八、常见问题8.1 predicates 不能跨表// ❌ 错误RdbPredicates 只能作用于一张表constpredicatesnewrelationalStore.RdbPredicates(handwriting)// 无法同时查询 report 表的字段// ✅ 正确分两次查询或使用原始 SQL JOINconsthandwritingawaitHandwritingDao.findById(id)constreportawaitReportDao.findByHandwriting(handwriting.id!)8.2 每次查询创建新的 predicates// ✅ 正确每个方法内部创建新的 predicatesstaticasynclistByArchive(archiveId:number):PromiseHandwritingEntity[]{constpredicatesnewrelationalStore.RdbPredicates(TABLE)predicates.equalTo(archive_id,archiveId)// ...}// ❌ 错误复用 predicates 对象状态污染constglobalPredicatesnewrelationalStore.RdbPredicates(TABLE)总结本文全面解析了鸿蒙 RDB 中RdbPredicates的用法基础用法new RdbPredicates(TABLE) 条件方法 store.query(predicates, COLS)常用条件equalTo、orderByDesc、isNull覆盖了项目中 90% 的查询场景组合条件beginWrap()/or()/endWrap()构建 OR 嵌套链式调用方法链清晰表达查询意图与原始 SQL 互补简单查询用 RdbPredicates复杂聚合用 querySql下一篇文章将介绍ValuesBucket 数据插入——create 方法的 ValuesBucket 构建。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力参考资源RdbPredicates API 参考RdbStore.query 方法[UserDao 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/features/data/UserDao.ets)[HandwritingDao 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/features/data/HandwritingDao.ets)[ArchiveDao 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/features/data/ArchiveDao.ets)[ReportDao 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/features/data/ReportDao.ets)[RelationDao 项目源码](file:///Users/fiona/Downloads/bijixinli/harmony-app/entry/src/main/ets/features/data/RelationDao.ets)鸿蒙数据持久化指南HarmonyOS 开发文档七、RdbPredicates 与原始 SQL 对比对于项目中的查询需求RdbPredicates 和原始 SQL 各有适用场景场景RdbPredicates原始 SQL单表简单查询✅ 推荐链式可读可用但过于繁琐多条件组合✅ and/or 组合可用聚合统计COUNT/SUM❌ 不支持✅ 必须用 SQL多表 JOIN❌ 不支持✅ 必须用 SQL动态条件构建✅ 链式追加条件需要字符串拼接SQL 注入安全✅ 自动参数化需要手动参数绑定7.1 等效示例相同查询的两种写法对比// RdbPredicates 写法constprednewrelationalStore.RdbPredicates(handwriting)pred.equalTo(user_id,userId).orderByDesc(created_at).limit(10)constrsawaitstore.query(pred,[id,created_at,image_path])// 原始 SQL 写法constsqlSELECT id, created_at, image_path FROM handwriting WHERE user_id ? ORDER BY created_at DESC LIMIT 10constrs2awaitstore.querySql(sql,[userId])两种方式在功能上等效RdbPredicates 可读性更好SQL 方式更灵活。7.2 选择建议简单 CRUD 操作→ 优先使用 RdbPredicates代码更安全易读聚合统计、JOIN 查询→ 使用querySql原始 SQL动态多条件筛选→ RdbPredicates 链式调用更优雅复杂报表查询→ SQL 表达力更强直接写 SQL如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力