ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MikroORM 与 Knex 的兼容桥梁:@mikro-orm/knex-compat 使用与源码解析

MikroORM 与 Knex 的兼容桥梁:@mikro-orm/knex-compat 使用与源码解析 后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载本篇技术指南围绕 MikroORM 官方兼容包mikro-orm/knex-compat展开它解决了在 MikroORM 查询em.find、em.createQueryBuilder等中直接复用既有 KnexQueryBuilder与knex.raw()表达式的问题把这些对象统一转换为 MikroORM 的RawQueryFragment。读完本文你将掌握该包的安装方式、raw助手的两种典型用法作为对象键与作为子查询值、它与mikro-orm/core自带raw()的分工边界以及其底层实现的转换原理与运行时安全机制。为什么需要这个兼容包MikroORM 的 SQL 驱动底层原本依赖 knex 构建查询而在 v6.5 之后的演进中项目逐步用 kysely 取代 knex 执行查询相关计划与说明见 docs/blog/2025-08-27-mikro-orm-6-5-released.md 中 knex being replaces with kysely for query execution 一节。因此SQL 驱动重新导出的raw助手见 packages/sql/src/query/raw.ts在检测到对象带有compile方法时按 KyselyQueryBuilder处理而无法直接识别 knex 的QueryBuilder与Raw实例。对于仍然使用 knex 编写 SQL 表达式的存量代码mikro-orm/knex-compat正是为这一迁移场景提供的官方兼容层它导出一个raw助手接受 knexQueryBuilder和Raw实例并将其转换成 MikroORM 可以理解的RawQueryFragment对象使这些既有表达式可以无缝进入 MikroORM 的查询体系。包的功能定位在 packages/knex-compat/README.md 开头有明确说明。安装与依赖约束npm install mikro-orm/knex-compat knex其中knex是 peer dependency需要单独安装。查看 packages/knex-compat/package.json 可以看到完整的约束peerDependenciesmikro-orm/sql版本与当前包严格对齐如7.2.1以及knex: ^3.0.0engines.node要求 Node.js 22.17.0包以 ESM 形式发布type: module入口指向 packages/knex-compat/src/index.ts。这意味着使用该包的项目应同时装有对应版本的mikro-orm/sql通常由你使用的 SQL 驱动包间接提供和 knex v3。核心用法把 knex 表达式传入 MikroORM 查询从该包导入的raw助手可以直接用在em.find的过滤条件中既能作为对象键key也能作为值value——这也是 MikroORM 中原始 SQL 片段的标准使用形态。场景一作为对象键传入knex.raw()实例import { raw } from mikro-orm/knex-compat; import knex from knex; const k knex({ client: pg }); // Pass a knex.raw() instance await em.find(User, { [raw(k.raw(lower(name)))]: name.toLowerCase() });这里k.raw(lower(name))是 knex 的原生原始表达式经过兼容层转换后作为过滤条件的键等价于在 SQL 中生成where lower(name) ?形式的条件并把name.toLowerCase()作为绑定参数。场景二作为值传入 knex QueryBuilder 子查询// Pass a knex QueryBuilder instance const subquery k(book) .count(*) .where(author_id, k.raw(??, [author.id])); await em.find(Author, { [raw(subquery)]: { $gt: 5 } });这里把整个 knex 子查询对象作为条件键raw(subquery)配合$gt: 5操作符最终生成类似where (select count(*) from book where author_id author.id) 5的查询。注意 knex 中??占位符用于标识符这里是列名author.id这正是 knex 写法本身的特点。与mikro-orm/core自带raw()的分工原文档特别强调对于不带 knex 的普通字符串 SQL 片段应直接使用mikro-orm/core的raw()助手只有当你手里已经有现成的 knex 表达式需要集成时才需要这个兼容包。例如import { raw } from mikro-orm/core; // 普通字符串片段直接用 core 的 raw await em.find(User, { [raw(lower(name))]: name.toLowerCase() });关于raw()助手的完整能力命名参数、数组参数、过滤器、索引表达式、sql标签模板、sql.ref()/sql.now()/sql.lower()等可进一步参考 docs/docs/raw-queries.md 的官方指南。底层原理rawKnex 是如何转换的整个包的核心实现只有两个文件packages/knex-compat/src/index.ts 把rawKnex以raw的名字重新导出packages/knex-compat/src/raw.ts 定义了rawKnex函数本体。rawKnex的转换逻辑packages/knex-compat/src/raw.ts非常精炼核心是“鸭子类型”检测export function rawKnexR RawQueryFragment symbol, T extends object any( sql: | QueryBuilderLike | Knex.QueryBuilder | Knex.Raw | EntityKeyT | EntityKeyT[] | AnyString | ((alias: string) string) | RawQueryFragment, params?: readonly unknown[] | Dictionaryunknown, ): R { if (Utils.isObjectKnex.QueryBuilder | Knex.Raw(sql) toSQL in sql) { const query sql.toSQL(); return raw(query.sql, query.bindings); } return raw(sql, params); }可以拆解为三步类型判断通过Utils.isObject(...) toSQL in sql识别 knex 对象。无论是 knex 的QueryBuilder还是Raw实例都实现了toSQL()方法这是与 KyselyQueryBuilder其标志方法是compile()区分的关键特征——后者由 packages/sql/src/query/raw.ts 中的 SQL 驱动版raw负责处理编译取参调用sql.toSQL()得到{ sql, bindings }即 knex 最终生成的 SQL 字符串与按顺序排列的绑定参数委托转换把编译结果交给mikro-orm/sql的raw(query.sql, query.bindings)由其构造RawQueryFragment实例。也就是说兼容包本身不做 SQL 生成它只是把 knex 的编译产物“翻译”成 MikroORM 认识的数据结构后续的别名替换、参数绑定、方言引号处理全部交由 MikroORM 原有管线完成。RawQueryFragment既是值也是键的运行时安全机制转换的最终产物RawQueryFragment定义在 packages/core/src/utils/RawQueryFragment.ts它保证原始片段可以在两个位置使用作为值直接赋值给属性或过滤条件值作为键通过Symbol.toPrimitiveRawQueryFragment.ts在需要字符串化时返回一个唯一 Symbol 作为对象键同时把该 Symbol 与片段实例登记到内部rawQueryReferences弱引用表keygetter 见 RawQueryFragment.ts。序列化得到的键会被缓存ORM 只识别“已登记的已知片段键”isKnownFragmentSymbol/getKnownFragment静态方法这带来一层运行时安全普通字符串、JSON 载荷或其他对象无法伪造被 ORM 认可的原始 SQL 键防止注入类误用。测试验证三种输入形态的等价输出仓库测试直接验证了该兼容包的行为见 tests/features/entity-manager/EntityManager.postgre.test.ts 的em.find with knex query用例pglite 版本见 tests/features/entity-manager/EntityManager.pglite.test.ts。测试覆盖三种输入// 1) MikroORM 自己的 QueryBuilder同样可被兼容层接受 const qb1 orm.em.createQueryBuilder(Book2, b).select(b.uuid).where({ author: 1 }); await orm.em.find(Author2, { books: { $in: rawKnex(qb1) } }); // 2) knex.raw() 实例 const pg knex({ client: pg }); const raw1 pg.raw(select b.uuid_pk from book2 as b where b.author_id 2); await orm.em.find(Author2, { books: { $in: rawKnex(raw1) } }); // 3) knex QueryBuilder链式 select/from/where const raw2 pg.select(b.uuid_pk).from({ b: book2 }).where(b.author_id, 3); await orm.em.find(Author2, { books: { $in: rawKnex(raw2) } });测试对生成的 SQL 做了断言三种形态分别生成author_id取 1、2、3where b2.uuid_pk in (select b.uuid_pk from book2 as b where b.author_id N)这说明无论片段来自 MikroORM 自身 QueryBuilder、knex 原始表达式还是 knex 链式查询构建器经过兼容层转换后输出结构完全一致可以被$in等集合操作符直接使用。类似地在 v6.6 的发布说明 docs/blog/2025-11-11-mikro-orm-6-6-released.md 中也展示了em.find(User, { id: raw(knexRaw) })这一官方示例。适用边界与注意事项只处理 knex 对象rawKnex对非 knex 对象字符串、数组、回调、RawQueryFragment等会原样透传给mikro-orm/sql的raw因此它同时保留了普通raw()的全部能力但它的设计初衷仍是“knex 兼容”版本对齐该包与mikro-orm/sql的 peer 版本严格绑定当前为 7.2.1升级 MikroORM 时需同步升级兼容包Node 版本要求 Node.js 22.17.0部署环境需满足该前提优先使用原生raw()纯字符串 SQL 片段建议直接使用mikro-orm/core或 SQL 驱动导出的raw()兼容包只在确实需要集成既有 knex 表达式时引入避免不必要的依赖。小结mikro-orm/knex-compat是一个小而精准的桥接层它识别 knexQueryBuilder/Raw的toSQL()特征将其编译为 SQL 字符串与绑定参数后委托给 MikroORM 的raw()最终以带运行时安全校验的RawQueryFragment形式参与查询构建。对于正在从 knex 迁移到 kysely、或希望在新代码中复用历史 knex 表达式的 MikroORM 用户这是官方提供的标准集成入口相关实现与测试均可直接在本仓库中查阅。赞分享后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载相关推荐big-AGI 仓库中的 /tape-opens 技能基于转录本测量形状的会话堆栈展开回顾big AGI 仓库中的 /tape opens 技能基于转录本测量形状的会话堆栈展开回顾 导读 本文介绍 big AGI 仓库中沉淀的一套 Claude C后端Drizzle ORM与其他ORM对比Prisma、Kysely、Knex优缺点分析Drizzle ORM与其他ORM对比Prisma、Kysely、Knex优缺点分析 Drizzle ORM是一个现代化的TypeScript ORM库专为后端数据库ORMObjection.js 入门指南基于Knex的Node.js ORM框架Objection.js 入门指南基于Knex的Node.js ORM框架 什么是Objection.js Objection.js 是一个基于 Knex 构数据库后端上一篇Play Integrity Fix终极Android设备完整性验证修复方案下一篇WCDB数据库框架实战指南5个关键步骤构建跨平台数据层解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表