ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

在纯 JavaScript 中使用 MikroORM:defineEntity 与 EntitySchema 实体定义完全指南

在纯 JavaScript 中使用 MikroORM:defineEntity 与 EntitySchema 实体定义完全指南 后端【免费下载链接】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 作为一款基于 Data Mapper、Unit of Work 与 Identity Map 模式的 TypeScript ORM并不强制要求项目使用 TypeScript 或装饰器语法。本指南围绕官方文档 docs/docs/usage-with-js.md 展开系统讲解如何在纯 JavaScriptvanilla JS项目中通过defineEntity帮助函数与EntitySchema两种方式完整定义实体、配置关联关系、注册并操作数据库同时结合仓库源码packages/core/src/entity/defineEntity.ts、packages/core/src/metadata/EntitySchema.ts与测试tests/defineEntity.test.ts揭示其底层原理。读完本文你将能够在无 TypeScript、无装饰器的环境中以全功能方式使用 MikroORM。无装饰器实体定义的两条路径在 JavaScript 项目中定义 MikroORM 实体官方提供两种等价方式二者最终都会生成EntitySchema实例并交由 ORM 元数据层处理方式定位适用场景defineEntity 属性构建器p推荐方式具备完整类型推断、API 更简洁大多数 JavaScript 项目尤其是希望保留声明式、链式风格的场景EntitySchema直接实例化底层 API属性以普通对象描述需要更细粒度控制、或已有类似元数据结构的项目从源码看defineEntity本身就建立在EntitySchema之上它的返回值就是一个带完整类型信息的EntitySchema实例见 packages/core/src/entity/defineEntity.ts 对EntitySchema的导入与使用以及 packages/core/src/metadata/EntitySchema.ts 中class EntitySchema的定义。因此两条路径最终殊途同归区别主要体现在属性声明语法与类型推断的体验上。使用defineEntity推荐的实体定义方式defineEntity帮助函数配合属性构建器p是官方在 JavaScript 中定义实体的首选方案。p是defineEntity.properties的简写别名源码中可见defineEntity.properties propertyBuilders;的赋值见 packages/core/src/entity/defineEntity.ts提供了覆盖全部内置类型的链式构建器。以下是一个完整的作者Author、书籍Book、书签BookTag三实体示例完整继承自官方文档import { defineEntity, p } from mikro-orm/core; import { Book } from ./Book.js; export const Author defineEntity({ name: Author, properties: { id: p.integer().primary(), name: p.string(), email: p.string().unique(), age: p.integer().nullable(), termsAccepted: p.boolean().default(false), born: p.date().nullable(), createdAt: p.datetime().onCreate(() new Date()), updatedAt: p.datetime().onCreate(() new Date()).onUpdate(() new Date()), books: () p.oneToMany(Book, { mappedBy: author }), favouriteBook: () p.manyToOne(Book).nullable(), }, });import { defineEntity, p } from mikro-orm/core; import { Author } from ./Author.js; import { BookTag } from ./BookTag.js; export const Book defineEntity({ name: Book, properties: { id: p.integer().primary(), title: p.string(), author: () p.manyToOne(Author), tags: () p.manyToMany(BookTag), }, });import { defineEntity, p } from mikro-orm/core; export const BookTag defineEntity({ name: BookTag, properties: { id: p.integer().primary(), name: p.string(), }, });标量属性构建器速览p上的标量构建器与 MikroORM 内置类型一一对应常用组合如下构建器映射类型常用链式修饰p.string()字符串varchar/text.primary()、.unique()、.nullable()、.default(value)p.integer()整数.primary()、.autoincrement()、.unsigned()p.bigint()大整数.primary()、.autoincrement()p.float()/p.decimal()浮点 / 高精度小数.precision()、.scale()p.boolean()布尔.default(false)p.date()日期.nullable()、.onCreate()p.datetime()日期时间.onCreate()、.onUpdate()p.time()时间.nullable()p.uuid()UUID.primary()p.json()JSON.nullable()、.lazy()p.array()/p.enum(items)数组 / 枚举.nullable()p.type(T)自定义类型配合 自定义类型 使用这些构建器还支持onCreate、onUpdate生命周期钩子onCreate在实体首次持久化时执行onUpdate在每次更新时执行二者均可返回函数值如() new Date()是维护createdAt/updatedAt时间戳的标准做法。关系属性构建器关系属性需要写成返回构建器的箭头函数() p.xxx(...)以便延迟解析目标实体、避免循环依赖问题构建器对应关系关键参数 / 修饰p.oneToOne(Target)一对一1:1.owner()、.inversedBy(prop)p.manyToOne(Target)多对一m:1.inversedBy(prop)、.nullable()、.ref()p.oneToMany(Target, { mappedBy })一对多1:m必须指定mappedBy指向对方实体上的反向属性p.manyToMany(Target)多对多m:n.inversedBy(prop)、.owner()、.fixedOrder()在Author示例中books: () p.oneToMany(Book, { mappedBy: author })通过mappedBy显式指定反向属性favouriteBook: () p.manyToOne(Book).nullable()则声明一个可空的多对一引用。对于 m:1 / 1:1 关系还可以通过.ref()把运行期值包装为Reference获得编译期安全与懒加载能力详见 类型安全的关联。与类结合使用获得自定义方法与实例化能力defineEntity除了接受name字符串外还可以直接传入class。这样实体名自动从类名推断你可以用new Author()创建实例并在类上定义自定义方法import { defineEntity, p } from mikro-orm/core; export class Author { id; name; email; getDisplayName() { return ${this.name} ${this.email}; } } export const AuthorSchema defineEntity({ class: Author, properties: { id: p.integer().primary(), name: p.string(), email: p.string().unique(), }, });定义后ORM 中既可引用AuthorSchema也可直接引用Author类——源码中EntitySchema通过全局REGISTRY基于Symbol.for存储在globalThis上见 packages/core/src/metadata/EntitySchema.ts建立了类 → Schema的反向查找因此二者在entities配置与em.create()中可互换使用。更推荐的进阶写法是defineEntity class扩展模式先定义 schema再让业务类继承自动生成的类并通过setClass()注册从而获得干净的类型提示、更优的性能与无重复的属性定义详细对比参见 defineEntity 专项文档const AuthorSchema defineEntity({ name: Author, properties: { id: p.integer().primary(), name: p.string(), books: () p.oneToMany(Book, { mappedBy: author }), }, }); class Author extends AuthorSchema.class { fullName() { return ${this.firstName} ${this.lastName}; } } AuthorSchema.setClass(Author);注意setClass()必须在 ORM 的实体发现MikroORM.init()之前、即模块加载时立即调用。复用公共属性多个实体共享id、createdAt、updatedAt等基础属性时可将构建器对象抽离后通过展开运算符组合const p defineEntity.properties; const baseProperties { id: p.integer().primary(), createdAt: p.datetime().onCreate(() new Date()), updatedAt: p.datetime() .onCreate(() new Date()) .onUpdate(() new Date()), }; const BookSchema defineEntity({ name: Book, properties: { ...baseProperties, title: p.string(), author: () p.manyToOne(Author), }, });注册实体并初始化 ORM实体定义完成后将其加入MikroORM.init()的entities数组import { MikroORM } from mikro-orm/sqlite; import { Author } from ./entities/Author.js; import { Book } from ./entities/Book.js; import { BookTag } from ./entities/BookTag.js; const orm await MikroORM.init({ entities: [Author, Book, BookTag], dbName: my-db-name, });几点实战建议参见 快速上手显式传入实体引用是最可靠的方式避免路径发现带来的不确定性若使用文件夹发现如entities: [./dist/entities]可用npx mikro-orm debug命令核查实际生效的路径。同步初始化纯 JS 项目还可以用new MikroORM({ ... })同步构造但该方式不支持文件夹发现、不会自动加载 ORM 扩展且在启用元数据缓存时需显式配置FileCacheAdapter。自动关闭连接ORM 实例实现了Symbol.asyncDispose可配合显式资源管理语法await using orm await MikroORM.init({ ... })在作用域结束时自动调用orm.close()该语法要求 Node 24 或由转译器降级处理。实体实例的创建与持久化通过em.create()创建实体实例create默认即标记为待持久化随后em.flush()一次性落库const author em.create(Author, { name: Jon Snow, email: jonwall.st, }); const book em.create(Book, { title: My Life on the Wall, author, }); await em.flush();flush是 Unit of Work 的提交点它会计算变更集change-set自动决定执行insert还是update尚未持久化无标识符的关联实体引用会级联持久化。查询侧则使用em.find()、em.findOne()、em.findAll()等方法配合populate选项加载关联集合。更完整的 EntityManager 用法见 EntityManager 文档。使用EntitySchema更底层的控制如果你偏好更贴近元数据的声明方式可以直接实例化EntitySchema属性以普通对象描述关系通过kind字段标识import { EntitySchema } from mikro-orm/core; export const Author new EntitySchema({ name: Author, properties: { id: { type: number, primary: true }, name: { type: string }, email: { type: string, unique: true }, age: { type: number, nullable: true }, termsAccepted: { type: boolean, default: false }, born: { type: Date, nullable: true }, createdAt: { type: Date, onCreate: () new Date() }, updatedAt: { type: Date, onCreate: () new Date(), onUpdate: () new Date() }, books: { kind: 1:m, entity: () Book, mappedBy: author }, favouriteBook: { kind: m:1, entity: () Book, nullable: true }, }, });其中type除字符串外也可直接使用String/Number/Boolean/Date等构造函数作为值。关系kind取值对照表kind字段用于声明属性与目标实体之间的关系类型完整取值如下ValueRelationship1:1One-to-onem:1Many-to-one1:mOne-to-manym:nMany-to-manyembeddedEmbedded或者使用ReferenceKind枚举替代字符串例如ReferenceKind.MANY_TO_ONE对应枚举定义见 packages/core/src/enums.ts 中的ReferenceKind。这一设计与源码中EntitySchemaProperty类型保持一致关系属性必须是kind与entity懒加载函数的组合标量属性则使用type见 packages/core/src/metadata/EntitySchema.ts。EntitySchema 的完整配置项EntitySchema构造参数要求提供name或class二者其一提供class时extends可自动推断。其余可选配置项包括{ name: string; // 实体名与 class 二选一 class: Class; // 关联的实体类 extends: string; // 继承的基类名或基类 Schema tableName: string; // 表名collection 的别名 properties: { ... }; // 属性定义 indexes: { properties: string | string[]; name?: string; type?: string }[]; uniques: { properties: string | string[]; name?: string }[]; repository: () ConstructorEntityRepository; hooks: { beforeCreate?: [...]; afterCreate?: [...]; ... }; abstract: boolean; // 是否为抽象实体 orderBy: QueryOrderMap | QueryOrderMap[]; // 默认排序 }完整类型声明可查看 packages/core/src/metadata/EntitySchema.ts 的EntitySchemaMetadata。源码级原理defineEntity 与 EntitySchema 的关系元数据等价测试 tests/defineEntity.test.ts 反复验证同一实体用defineEntity与EntitySchema两种写法产生的元数据完全一致如expect(Foo.meta).toEqual(asSnapshot(FooSchema.meta))证明defineEntity是EntitySchema之上的语法糖。类型推断defineEntity借助InferEntity/InferEntityFromProperties类型工具见 packages/core/src/entity/defineEntity.ts把属性构建器的链式调用结果映射为实体类型并在测试中以conditional-type-checks的IsExact做编译期断言。构建器链PropertyChain接口packages/core/src/entity/defineEntity.ts定义了所有链式修饰方法的签名并在类型层面按属性kind约束可用方法例如.mappedBy()仅对1:m/1:1/m:n有效错误用法在编译期即被拒绝。全局注册表EntitySchema.REGISTRY存储类 ↔ Schema映射使实体类可以直接出现在entities配置中也规避了 CJS/ESM 双包加载问题。字符串归一化p.string()等构建器还支持.trim()、.uppercase()/.lowercase()、.length()等归一化修饰见 tests/defineEntity.test.ts 首个用例这些选项会被合并进属性元数据。纯 JS 项目中的 CLI 与配置实战虽然纯 JS 项目没有 TypeScript 编译步骤但 MikroORM 的 CLImikro-orm/cli依然可用。安装mikro-orm/cli版本需与mikro-orm/core对齐后通过npx mikro-orm即可执行schema:update、migration:create、seeder:run等命令。CLI 会按以下顺序相对当前工作目录查找配置文件./src/mikro-orm.config.ts./mikro-orm.config.ts./dist/mikro-orm.config.js./build/mikro-orm.config.js./src/mikro-orm.config.js./mikro-orm.config.js纯 JS 项目通常使用.js配置文件即可也可在package.json的mikro-orm.configPaths中显式指定候选路径列表。相关环境变量包括MIKRO_ORM_CLI_CONFIG配置文件路径、MIKRO_ORM_CLI_ALWAYS_ALLOW_TS、MIKRO_ORM_CLI_VERBOSE等。在 JS 配置文件中推荐使用defineConfig帮助函数它在无 JSDoc 类型注解的情况下也能获得编辑器智能提示且从驱动包导入时自动推断driver选项// mikro-orm.config.js import { defineConfig } from mikro-orm/sqlite; import { Author } from ./entities/Author.js; import { Book } from ./entities/Book.js; import { BookTag } from ./entities/BookTag.js; export default defineConfig({ entities: [Author, Book, BookTag], dbName: my-db-name, });若应用与 CLI 需要不同权限/数据库配置对象可导出数组各元素需有唯一contextName缺省视为default或用接收contextName参数的工厂函数按租户生成配置配合npx mikro-orm --contextNamexxx选择目标配置详见 快速上手 的Configuration file structure一节。小结纯 JavaScript 项目完全可以获得 MikroORM 的完整能力defineEntity 属性构建器p是首选路径声明直观、类型推断完整、关联关系表达清晰EntitySchema作为底层 API 提供了对元数据的完全掌控适合进阶定制。二者在源码层面同源packages/core/src/entity/defineEntity.ts 基于 packages/core/src/metadata/EntitySchema.ts 实现元数据等价性由 tests/defineEntity.test.ts 的用例持续保障。无论选择哪条路径实体注册、em.create()/flush()持久化、CLI 迁移与 schema 生成等后续环节均与 TypeScript 项目完全一致。官方还提供了完整的 Express JavaScript 示例应用express-js-example-app可供参考落地。更多细节可继续阅读 defineEntity 专项文档 与 快速上手。赞分享后端【免费下载链接】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点击查看免费下载相关推荐如何在nelsonlai.dev项目中运用TypeScript高级类型系统提升开发效率如何在nelsonlai.dev项目中运用TypeScript高级类型系统提升开发效率 nelsonlai.dev是一个基于TypeScript、Next.js后端WVP-PRO国标GB28181视频平台部署指南一条Docker命令10分钟接上第一路摄像头WVP PRO国标GB28181视频平台部署指南一条Docker命令10分钟接上第一路摄像头 WVP PRO 是一个基于 GB28181 2016 国标开源后端音视频前端在 JavaScript 中使用 TypeORMEntitySchema 实体定义与 DataSource 实战指南在 JavaScript 中使用 TypeORMEntitySchema 实体定义与 DataSource 实战指南 TypeORM 并非 TypeScrip后端数据库ORM上一篇gh_mirrors/trl/trl中的训练自动化失败分析工具下一篇Hacking Windows实战使用IDA Free动态调试x86/x64汇编代码的完整步骤创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表