ARTICLE DETAIL

资讯详情

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

MikroORM Entity Generator 完全指南:从已有数据库 Schema 反向生成 TypeScript 实体

MikroORM Entity Generator 完全指南:从已有数据库 Schema 反向生成 TypeScript 实体 后端【免费下载链接】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点击查看免费下载本指南基于 docs/versioned_docs/version-5.9/entity-generator.md 展开并结合当前仓库7.x中mikro-orm/entity-generator包的源码实现进行深度剖析。你将掌握两种调用方式CLI 命令与初始化脚本、全部高级配置选项的含义与优先级规则以及生成器从连接数据库 → 读取 Schema → 产出实体文件的底层工作流程从而在遗留数据库上快速建立与 MikroORM 对齐的实体层。在采用 MikroORM 重构或接管一个已有数据库的项目时最常见的诉求是别让我手写几十上百个实体类。MikroORM 提供的EntityGenerator帮助类正是为此而生——它连接现有数据库反向解析表结构、外键、枚举、存储例程等元数据并自动生成对应的 TypeScript 实体源码。本文以 v5.9 版本文档为核心骨架结合仓库当前实现源码packages/entity-generator/src/EntityGenerator.ts与类型定义packages/core/src/typings.ts完整讲解配置与实战细节。一、EntityGenerator 是什么从 Schema 到实体的逆向工程EntityGenerator是一个基于已有数据库 Schema反向生成实体源码的辅助工具。在 v5.9 时代它隶属于核心包而在当前 7.x 版本中它被拆分到独立包mikro-orm/entity-generator中见 packages/entity-generator/package.json并作为 ORM 扩展extension注册使用。从源码看生成器的核心工作并不神秘EntityGenerator构造时从 EntityManager 上取得 driver、platform、schema helper 与连接EntityGenerator.ts随后在generate()方法中完成读 Schema → 转元数据 → 输出源码三步通过DatabaseSchema.create()读取数据库表结构支持takeTables/skipTables过滤将每个表转换为EntityMetadata实体元数据并把外键等关系解析为对应属性依据entityDefinition选项选择SourceFile/DefineEntitySourceFile/EntitySchemaSourceFile三种渲染器输出实体源码字符串必要时写入磁盘。值得强调的是除了表实体生成器还会为原生枚举NativeEnumSourceFile和存储例程RoutineSourceFile如函数、存储过程生成对应源码这在 v5.9 文档中虽未展开但可从 EntityGenerator.ts 的循环中确认。二、快速开始CLI 一键生成v5.9 文档给出的第一种用法是 CLI 命令。使用前需要先本地安装mikro-orm/cli包且其版本必须与mikro-orm/core对齐。npx mikro-orm generate-entities --dump # Dumps all generated entities npx mikro-orm generate-entities --save --path./my-entities # Saves entities into given directory--dump别名-d把生成的实体源码打印到控制台适合快速预览--save别名-s把实体写入磁盘文件--path别名-p配合--save指定输出目录即./my-entities--schema只针对指定 schema 生成实体。以上参数可从 CLI 命令实现 packages/cli/src/commands/GenerateEntitiesCommand.ts 中确认若既不传--save也不传--dump命令会直接展示帮助信息成功保存后会输出Entities generated successfully。注意 CLI 初始化 ORM 时会强制设置discovery.warnWhenNoEntities false因为我们此时还没有任何实体需要关闭未发现实体的告警。v5.9 与当前版本的差异提示v5.9 的 CLI 直接可用而在当前 7.x 中CLI 的generate-entities命令底层同样调用orm.entityGenerator.generate(...)且要求项目里已安装并注册mikro-orm/entity-generator扩展见下文脚本方式。三、通过初始化脚本调用 EntityGeneratorCLI 之外v5.9 文档还给出了脚本方式适合把生成流程嵌入 CI、脚手架或需要编程控制选项的场景import { MikroORM } from mikro-orm/core; (async () { const orm await MikroORM.init({ discovery: { // we need to disable validation for no entities warnWhenNoEntities: false, }, dbName: your-db-name, // ... }); const generator orm.getEntityGenerator(); const dump await generator.generate({ save: true, baseDir: process.cwd() /my-entities, }); console.log(dump); await orm.close(true); })();随后通过ts-node运行或先编译为纯 JS 再用node执行$ ts-node generate-entities关键点拆解warnWhenNoEntities: false初始化时项目里还没有任何实体必须关闭无实体告警否则 ORM 启动会报错orm.getEntityGenerator()v5.9 的 API 入口generate({ save: true, baseDir: ... })save: true表示写盘baseDir指定输出目录await orm.close(true)任务结束后显式关闭连接true表示强制关闭返回值dump是字符串数组每个元素对应一个生成文件的源码内容可直接console.log或继续二次加工。当前版本迁移提示在 7.x 中getEntityGenerator()已改为通过扩展注册后的orm.entityGenerator且baseDir选项更名为path。当前GenerateOptions类型定义见 packages/core/src/typings.ts注册方式为在配置中声明extensions: [EntityGenerator]import { defineConfig } from mikro-orm/postgresql; import { EntityGenerator } from mikro-orm/entity-generator; export default defineConfig({ dbName: test, extensions: [EntityGenerator], });对应脚本调用为const dump await orm.entityGenerator.generate({ save: true, path: process.cwd() /my-entities, });四、高级配置选项详解v5.9 文档指出默认情况下EntityGenerator只生成关系中的 owning side拥有方如 M:1并使用装饰器定义实体。行为可通过 ORM 配置中的entityGenerator段调整。文档列出的选项如下bidirectionalRelations同时生成关系的 inverse side被拥有方/反向方identifiedReferences将 M:1 与 1:1 关系生成为 wrapped references引用包装entitySchema改用EntitySchema而非装饰器定义实体esmImport使用 ESM 风格导入例如esmImporttrue时生成import Author from ./Author.jsskipTables忽略指定数据库表接受表名数组skipColumns忽略指定表的某些列接受对象键为带 schema 前缀如有的表名值为列名数组。示例const dump await orm.entityGenerator.generate({ save: true, baseDir: process.cwd() /my-entities, skipTables: [book, author], skipColumns: { public.user: [email, middle_name], }, });选项优先级generate 参数 全局 entityGenerator 配置在当前源码实现中generate(options)的第一步就是合并配置options Utils.mergeConfig({}, this.#config.get(entityGenerator), options);见 EntityGenerator.ts这意味着你既可以在 ORM 配置的entityGenerator段设置全局默认行为也可以在每次调用generate()时传参覆盖——调用时传入的选项拥有更高优先级。这与新版文档GenerateOptions对象优先于全局配置的描述一致。完整选项清单当前版本含 v5.9 之外的新增项除了 v5.9 文档中的六项当前仓库的GenerateOptions还提供了更多精细控制可参看 packages/core/src/typings.ts选项说明path/save输出目录默认baseDir/generated-entities与是否写盘schema只对指定 schema 生成实体takeTables只考虑指定表接受字符串或RegExp被引用但未包含的表其外键会被当作不存在skipTables/skipColumns忽略表/列同样支持RegExpforceUndefined可空属性按不存在null值处理类型提示中省略nullundefinedDefaults把数据库上报的null默认值转为undefined属性变为可选entityDefinition实体定义输出方式decorators|defineEntity|entitySchema默认decoratorsinferEntityType与defineEntity搭配仅输出类型基于InferEntity而非类声明enumMode枚举输出方式ts-enum默认|union-type|dictionaryscalarTypeInDecorator在标量属性装饰器中直接写入type选项省去运行时发现scalarPropertiesForRelations外键列是否生成标量属性never默认|always|smartonlyPurePivotTables/outputPurePivotTables/readOnlyPivotTables控制 M:N 连接表的生成策略见下文customBaseEntityName/useCoreBaseEntity为实体附加自定义基类或使用mikro-orm/core的BaseEntitycoreImportsPrefix为来自 MikroORM 核心的导入添加别名前缀规避与表名/类型名冲突fileName/onImport/extraImports文件命名回调、导入解析回调与附加导入回调onInitialMetadata/onProcessedMetadata元数据处理钩子见下文元数据加工一个较为完整的组合示例来自新版文档展示了如何同时启用多项const dump await orm.entityGenerator.generate({ entitySchema: true, bidirectionalRelations: true, identifiedReferences: true, esmImport: true, save: true, path: process.cwd() /my-entities, skipTables: [book, author], skipColumns: { public.user: [email, middle_name], }, });五、源码级原理generate() 的完整工作流程阅读 EntityGenerator.ts 的generate()实现可以还原出一次完整生成的内部流程合并配置Utils.mergeConfig({}, config.get(entityGenerator), options)调用参数覆盖全局配置读取 SchemaDatabaseSchema.create(connection, platform, config, ...)传入takeTables/skipTables过滤表随后schema.loadRoutines()加载存储例程生成元数据getEntityMetadata()中按options.schema过滤表、按skipColumns删除列键使用table.getShortestName(false)即带 schema 前缀的表名并为每个表调用getEntityDeclaration()产出实体元数据EntityGenerator.ts降级悬空外键若某关系的目标表不在元数据集合中被skipTables/takeTables排除该关系会被降级为ReferenceKind.SCALAR普通标量属性仿佛外键不存在EntityGenerator.ts——这解释了文档中如果外键引用了被跳过的表生成的代码将如同该外键不存在的行为调用onInitialMetadata钩子在基类生成、M:N 检测、引用包装与双向关系检测之前处理元数据处理类名冲突不同 schema 下同名表生成同名的类时会自动以schema_className方式重命名并同步更新关系引用EntityGenerator.ts检测 M:N 关系detectManyToManyRelations()识别纯连接表复合主键 恰好两个 M:1 主键关系生成 M:N 属性清理冗余引用完整性规则FK 即主键、固定顺序连接表、指向复合主键的关系等默认规则不再显式输出cleanUpReferentialIntegrityRules按需生成bidirectionalRelations双向关系、identifiedReferences引用包装、customBaseEntityName自定义基类、undefinedDefaultsnull 默认值转 undefined依次生效调用onProcessedMetadata钩子在所有结构加工完成后、输出文件之前做最终调整渲染并输出按entityDefinition选择渲染器默认输出目录为${baseDir}/generated-entitiesEntityGenerator.ts。输出文件的安全边界一个值得注意的安全细节写盘前生成器会校验所有目标文件名必须落在项目目录或指定输出目录内任何试图逃逸到任意文件系统位置的文件名都会抛出Cannot generate ..., it resolves outside of the project folder错误EntityGenerator.ts。这保证了基于数据库表名拼接的文件路径不会被恶意利用。关系生成的三种核心策略默认owning side only只生成关系的拥有方属性如 M:1 的外键引用bidirectionalRelations: true为每个关系补充 inverse sideM:1 生成 1:M1:1 与 M:N 生成对应反向属性反向属性名由inverseSideName()推导若与已有属性冲突会自动追加数字后缀EntityGenerator.tsidentifiedReferences: true将 M:1、1:1 关系以及所有lazy属性标记为ref: true输出为Reference包装引用EntityGenerator.ts。M:N 连接表的智能识别detectManyToManyRelations()EntityGenerator.ts对连接表的判定条件相当严格非复合主键的表永远不可能是连接表只有复合主键 恰好两个均为 M:1 的主键关系的表才进入候选。此外连接表若含额外列如created_at默认仍生成 M:N除非onlyPurePivotTables: true额外列中有非空且唯一的列、或不可选属性时集合被视为只读仅在readOnlyPivotTables: true时生成并附带persist: false纯连接表默认不单独输出为实体文件除非被外键引用或outputPurePivotTables: true连接表存在自增主键时会被识别为固定顺序列fixedOrder生成带固定顺序的 M:N 集合。六、对生成元数据的二次加工onInitialMetadata / onProcessedMetadata数据库 Schema 无法表达所有业务信息因此 v5.9 之后版本提供了两个元数据处理钩子在写入文件前修改生成的实体元数据注意这与配置中的onMetadata钩子不同——onMetadata不影响实体文件而生成器选项里的这两个钩子会直接影响输出。适合在钩子里完成的操作包括为特定列/关系添加hidden标记序列化时隐藏添加序列化groups、lazy、eager、mapToPk、orphanRemoval、cascade等选项调整标量属性的type/runtimeType为自定义类型添加单表继承STI、Embedded内嵌实体、virtual 实体以及带formula的属性。例如让所有名为password的列变为懒加载且隐藏并让所有 M:N 关系在序列化时隐藏import { ReferenceKind, MikroORM } from mikro-orm/core; const orm await MikroORM.init({ // ORM config }); await orm.entityGenerator.generate({ onInitialMetadata: (metadata, platform) { metadata.forEach(meta { meta.props.forEach(prop { if (prop.name password) { prop.hidden true; prop.lazy true; } }); }); }, onProcessedMetadata: (metadata, platform) { metadata.forEach(meta { meta.props.forEach(prop { if (prop.kind ReferenceKind.MANY_TO_MANY) { prop.hidden true; } }); }); }, });钩子同样适合把 JSON 列改造为Embedded内嵌实体或在脚本中直接new EntityMetadata(...)创建 embeddable 元数据并推入集合生成器会据此在实体中输出Embedded({ entity: () IdentitiesContainer, array: true, object: true, prefix: false, nullable: true })之类的引用。由于元数据对象是内部结构修改时的校验较少出错信息可能不够直观建议在钩子中保持谨慎。七、当前限制与注意事项v5.9 文档明确指出的限制是MySQL 下tinyint列会被定义为 boolean 属性MySQL 没有真正的BOOLEAN类型该关键字只是TINYINT(1)的别名因此生成器只能将其映射为 boolean。当前版本文档在此基础上有两条补充MongoDB 不被支持EntityGenerator 面向关系型数据库的 Schema 反向工程文档型数据库不在其列生成实体默认不继承任何基类如需统一基类可使用customBaseEntityName自动创建同名基类并让所有无继承的实体继承它或useCoreBaseEntity继承mikro-orm/core的BaseEntity。此外还有两条实用建议esmImport: true会在导入语句中附加.js后缀以适配 ESM 运行时同时在不使用引用包装时生成器会为所有 M:1、1:1 关系加上Rel包装规避循环引用导致的Cannot access X before initialization类初始化顺序错误——这是当前版本新增的防坑机制。八、从测试看行为契约仓库中的测试可以作为上述行为的可验证依据tests/features/entity-generator/EntityGenerator.postgres.test.ts 验证了skipTables: [test2, test2_bars]后Test2.ts不再生成而Author2.ts、FooBar2.ts正常输出并断言Author2.ts存在、Test2.ts不存在另有takeTables与skipTables配合RegExp如/^foo_bar\d$/的测试tests/features/entity-generator/EntityGenerator.mysql.test.ts 以describe.each([true, false])组合遍历bidirectionalRelations与identifiedReferences的四种开关组合确认不同配置下的快照输出符合预期tests/features/entity-generator/MetadataHooks.mysql.test.ts 覆盖了onInitialMetadata/onProcessedMetadata钩子的实际效果。结语从 v5.9 到当前 7.xEntityGenerator 的核心理念始终如一读取数据库 Schema输出与 MikroORM 对齐的实体源码。默认生成 owning side、装饰器风格实体通过entityGenerator配置或generate()参数可以自由切换到双向关系、引用包装、EntitySchema/defineEntity定义方式、表列过滤、自定义类型与元数据钩子等高级模式。对遗留数据库接入 MikroORM 的场景而言这条Schema → 实体的逆向通道能显著降低手工建模成本而源码中的过滤降级、连接表识别与路径安全检查等细节则保证了生成结果在生产环境中的可用性与安全性。赞分享后端【免费下载链接】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 Entity Generator 实战从数据库 Schema 逆向生成 TypeScript 实体的完整指南MikroORM Entity Generator 实战从数据库 Schema 逆向生成 TypeScript 实体的完整指南 导读 本文围绕 MikroOR后端MikroORM Schema First 完整实战从既有数据库 Schema 反向生成可再生成实体并构建全栈应用MikroORM Schema First 完整实战从既有数据库 Schema 反向生成可再生成实体并构建全栈应用 本文基于 MikroORM 官方文档快照后端MikroORM Schema Generator 完全指南从实体元数据到数据库 Schema 的自动化管理MikroORM Schema Generator 完全指南从实体元数据到数据库 Schema 的自动化管理 导读 SchemaGenerator 是 Mik后端上一篇探索色彩的无限可能 —— Tint Shade Generator项目评测下一篇OneDiff 开源项目教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表