mikro-orm 原生 BigInt 主键实战指南:MySQL 与 PostgreSQL 下的 BigIntType 映射详解

📅 发布时间:2026/9/25 5:28:43
mikro-orm 原生 BigInt 主键实战指南:MySQL 与 PostgreSQL 下的 BigIntType 映射详解
后端【免费下载链接】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点击查看免费下载导读本文聚焦 mikro-orm 自 v6 起对bigint数据库主键的原生支持以 JS 内置BigInt类型为代表结合BigIntType类型构造器在bigint、string、number三种目标类型之间的映射策略讲解声明式装饰器与defineEntity两种实体定义方式下的完整用法、底层转换逻辑与精度边界。读完本文你将掌握在 MySQL 与 PostgreSQL 上安全使用bigint主键、按需切换主键的 JS 侧类型并理解BigIntType在数据库写入、JSON 序列化、游标比较等环节的具体行为从而避免大整数精度丢失这一常见坑。一、为什么需要专门讨论 bigint 主键在关系型数据库中BIGINT是 64 位有符号整数取值范围远超 JavaScriptNumber能安全表示的范围。JavaScript 的Number基于 IEEE 754 双精度浮点只能精确表示Number.MAX_SAFE_INTEGER2^53 - 1以内的整数超出该范围时会发生静默舍入。这意味着如果直接把数据库返回的BIGINT值塞进number用户 ID、订单号等超大主键可能被悄悄改写成错误值。mikro-orm 从 v6 开始改变了这一局面bigint数据库列默认映射为 JS 原生BigInt类型BigIntType 源码注释 明确说明该类型会将数据库返回的字符串自动转换为原生 bigint彻底绕开了Number的精度限制。用户文档 using-bigint-pks.md 与 defining-entities.md 中对该能力有完整阐述本文在此基础上结合 BigIntType 实现 与测试用例做纵深展开。二、声明式实体定义原生 BigInt 主键自 v6 起使用装饰器声明实体时bigint主键不再需要显式指定类型——mikro-orm 会自动识别bigint这一运行时类型并将其映射为数据库的BIGINT列import { Entity, PrimaryKey } from mikro-orm/core; Entity() export class User { PrimaryKey() id: bigint; }这里的bigint是 TypeScript 内置类型对应 JS 原生BigInt。ORM 在数据库侧生成bigint列MySQL、PostgreSQL 均可在应用侧以BigInt字面量如1n、2n读写。测试 GH482.test.ts 中正是这样声明实体并在运行中用job.id 1n赋值、最终断言 Identity Map 键为Job-public:1验证了bigint主键在整个生命周期插入、删除、identity map中的行为。三、BigIntType按需切换映射目标类型默认情况下bigint映射为 JS 原生BigInt。若你的应用场景需要其他 JS 侧类型例如对接旧代码、JSON 传输、UI 展示可以通过BigIntType构造器显式指定目标类型。BigIntType的泛型参数Mode限定了三种合法模式bigint | number | stringBigIntType 类型定义。import { BigIntType, Entity, PrimaryKey } from mikro-orm/core; Entity() export class User { // 默认行为等价于直接写 bigint 属性 PrimaryKey({ type: new BigIntType(bigint) }) id1: bigint; // 映射为 string完全保留精度适合 JSON 序列化场景 PrimaryKey({ type: new BigIntType(string) }) id2: string; // 映射为 number仅当值不超过 2^53 - 1 时安全 PrimaryKey({ type: new BigIntType(number) }) id3: number; }三种模式的取舍模式JS 侧类型精度适用场景bigint默认bigint完整 64 位精度推荐默认选择ORM 内部全链路以字符串承载stringstring完整 64 位精度JSON 传输、需要与字符串 ID 兼容的旧系统numbernumber仅 2^53 - 1 以内安全自增主键等值较小、确定不会超界的场景官方文档明确警告JavaScript 无法在映射到number类型时表示bigint的全部可能取值——只有不超过Number.MAX_SAFE_INTEGER2^53 - 1的值才被安全支持。使用number模式前务必评估主键取值范围。BigIntType同时也被收录在 types 注册表 中键名为bigint因此你也可以通过Property({ type: types.bigint })或PrimaryKey({ type: types.bigint })引用它。四、defineEntity 定义方式下的 bigint 主键如果项目采用 schema-first 的defineEntityAPI而非装饰器可以通过属性构建器p.bigint()声明主键。用户指南 01-first-entity.md 指出使用p.bigint()构建器时BigInt 默认映射为string因为 JSnumber无法安全表示大整数而 defining-entities.md 给出了完整的defineEntity主键示例import { defineEntity, p } from mikro-orm/core; const SomeEntity defineEntity({ name: SomeEntity, properties: { id: p.bigint().primary(), }, });配合 class 使用同样可行const SomeEntitySchema defineEntity({ name: SomeEntity, properties: { id: p.bigint().primary(), }, }); export class SomeEntity extends SomeEntitySchema.class {} SomeEntitySchema.setClass(SomeEntity);在 quick-start.md 的 SQL 起步示例中也能看到id: p.bigint().primary()与id!: bigint的对应用法说明 schema-first 与装饰器两条路径对 bigint 主键的支持是并行完整的。五、底层实现BigIntType 的转换链路理解BigIntType的底层实现有助于准确预判各种边界行为。源码 BigIntType.ts 的核心逻辑如下5.1 写入数据库统一转为十进制字符串convertToDatabaseValue将 JS 侧值一律转换为字符串后再交给驱动实现见 L18-L24。测试 GH482.test.ts 中可见实际生成的 SQL 形如insert into job (id, optional) values (2, 1)、update job set optional 1 where id 2——bigint 值以字符串字面量写入 SQL这正是 MySQL / PostgreSQL 驱动安全传输 64 位整数的方式。5.2 从数据库读取按模式转换convertToJSValue根据构造时指定的mode分派实现见 L26-L41numberNumber(value)超出安全整数范围会静默舍入——这正是官方警告的根源stringString(value)无损保留bigint默认BigInt(String(value))无损保留为原生bigint。同时compareAsType()返回模式名bigint/string/numbercompareValues()以字符串形式比较确保 Identity Map 和变更检测在三种模式下行为一致实现见 L83-L89。5.3 JSON 序列化与反序列化额外校验toJSON在number模式下直接返回数值其余模式返回十进制字符串fromJSON则只接受十进制整数字符串或整数number否则抛出ValidationError.invalidType实现见 L43-L77。特别地在number模式下fromJSON还会用Number.isSafeInteger二次校验——源码注释明确指出Number会在超出MAX_SAFE_INTEGER时静默舍入因此被篡改的游标必须大声失败。这为游标分页、序列化回填等场景提供了防精度丢失的兜底。5.4 列类型声明委托给平台getColumnType委托给platform.getBigIntTypeDeclarationSQL(prop)实现见 L79-L81基础平台默认返回bigintPlatform.getBigIntTypeDeclarationSQL。各方言驱动postgresql / mysql / mariadb 等可基于该钩子定制具体的 DDL 声明schema 生成器据此产出BIGINT列定义。六、与其他 bigint 相关机制的联动6.1 可作为外键/复合主键的组成bigint主键完全可以作为其他实体ManyToOne的引用目标。测试 GH482.test.ts 即演示了Jobid: bigint作为Level复合主键一部分的用法ManyToOne({ primary: true }) job!: Job并验证了孤儿删除、复合键 join 等行为。6.2 可空 bigint 属性GH482.test.ts 同时覆盖了Property({ type: BigIntType, nullable: true })的可空 bigint 属性赋1n、置null、置undefined的多次 flush 均正确落库为1或null读取回填后undefined归一为null。这说明BigIntType对null/undefined的透传是完备的convertToDatabaseValue 对 null 直接返回。6.3 复合主键命名约定文档 composite-keys.md 提到当实体主键是名为id、_id或uuid的单一标量主键类型为number | string | bigint之一时无需额外配置PrimaryKeyProp。因此PrimaryKey() id: bigint属于免配置的常规情形。七、使用建议与精度红线总结默认使用原生bigint自 v6 起PrimaryKey() id: bigint是最简洁且精度无损的写法无需手动引入BigIntType。需要 string 时显式声明与外部系统通过 JSON 交换 ID 时new BigIntType(string)可避免 JSON 序列化把BigInt变成字符串丢失类型语义。慎用number模式仅当主键值域确定不超过Number.MAX_SAFE_INTEGER2^53 - 1时才使用一旦超界写入前静默舍入、游标校验失败fromJSON抛错都会成为问题信号。schema-first 用户走p.bigint()defineEntity下p.bigint().primary()即声明 bigint 主键默认映射为string如需原生bigint可结合BigIntType进一步定制。可空与外键场景放心用从源码与测试看BigIntType对null/undefined透传、复合主键、关系引用均有完整覆盖。延伸阅读实体定义完整指南含 bigint 主键多方式对比defining-entities.md自定义类型体系与BigIntType在类型注册表中的位置custom-types.md、types/index.tsbigint 主键与 defineEntity 结合示例quick-start.md类型转换底层实现BigIntType.ts平台层列声明钩子Platform.ts相关回归测试GH482.test.ts赞分享后端【免费下载链接】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点击查看免费下载相关推荐mikro-orm 原生 BigInt 主键实战MySQL 与 PostgreSQL 下的精度安全实践mikro orm 原生 BigInt 主键实战MySQL 与 PostgreSQL 下的精度安全实践 本文基于 mikro orm 官方文档 Using n后端Hibernate ORM JSON数据类型映射PostgreSQL与MySQL JSONB教程Hibernate ORM JSON数据类型映射PostgreSQL与MySQL JSONB教程 你是否还在为JSON数据在关系型数据库中的存储和查询烦恼本后端数据库ORMDoctrine ORM 复合主键完整实战指南从基础映射到派生标识Doctrine ORM 复合主键完整实战指南从基础映射到派生标识 导读 本文以 docs/en/tutorials/composite primary k数据库ORM后端上一篇Rsbuild 项目中的 TypeScript 支持详解下一篇如何快速部署PowerDNS-AdminuWSGINginx完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考