后端【免费下载链接】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 v5.9 官方迁移文档系统讲解 MikroORM 内置迁移机制的完整使用链路从Migration基类编写、migration:create生成 Schema Diff 迁移、快照Snapshot机制、核心配置项到 CLI 命令、编程式调用、生产环境部署以及 MongoDB 支持与已知限制。读完本文你将能够为 SQL 或 MongoDB 驱动项目搭建一套可回滚、可审计、可自动化执行的数据库迁移流程并理解其底层执行原理。使用迁移功能前需先安装对应驱动包SQL 驱动使用mikro-orm/migrationsMongoDB 使用mikro-orm/migrations-mongodb。迁移机制概述MikroORM 通过 umzug 提供对迁移的集成支持它允许我们基于当前数据库 Schema 与实体定义之间的差异自动生成迁移文件。迁移文件存储时不带扩展名自 v5 起。在事务行为上默认情况下每个迁移各自在事务内执行且所有迁移整体被包裹在一个主事务master transaction中因此只要其中任何一个迁移失败全部变更都会被回滚对应配置项migrations.allOrNothing默认true。从源码结构看迁移子系统由packages/migrations/src下的几个核心类协作完成Migration.ts —— 迁移基类用户编写的每个迁移文件都继承它MigrationRunner.ts —— 负责在事务上下文内执行单个迁移的up/downMigrationStorage.ts —— 负责在数据库中维护已执行迁移的记录表Migrator.ts —— 总调度器实现迁移的创建、执行、回滚与快照管理TSMigrationGenerator.ts / JSMigrationGenerator.ts —— 负责把 Schema Diff 渲染成迁移源码文件。编写迁移类Migration class迁移文件本质上是继承自Migration抽象类的 TypeScript 类必须实现up()方法并通过this.addSql()向迁移队列添加 SQL 语句import { Migration } from mikro-orm/migrations; export class Migration20191019195930 extends Migration { async up(): Promisevoid { this.addSql(select 1 1); } }如果想支持撤销可以实现down()方法——它的默认实现是抛出This migration cannot be reverted错误见 Migration.ts。事务控制每个迁移默认被包裹在一个事务中。可以通过实现isTransactional(): boolean方法按迁移粒度覆盖该行为返回false表示该迁移不在事务内执行。Migration基类中该方法的默认实现为返回true见 Migration.ts。Configuration配置对象和 driver 实例在Migration类上下文中均可访问作为构造参数注入见 Migration.ts。执行查询execute()与getKnex()可以通过Migration.execute()方法在迁移中执行查询它会与迁移的其余语句在同一个事务中运行await this.execute(update book set title ? where id ?, [foo, 1]);execute()接受三种查询形式原始 SQL 字符串、raw()生成的 SQL 片段、或 native query builder 实例Query类型定义见 Migration.ts参数数组仅在第一个参数为字符串 SQL 时生效底层最终通过driver.execute(sql, params, all, this.ctx)执行见 Migration.ts。Migration.addSql()方法同样接受 knex 实例可通过Migration.getKnex()获取 knex 实例SQL 驱动场景下可用。在迁移中使用EntityManager迁移的主要用途是修改 SQL Schema但也可以用它来修改数据方式有两种this.execute()或通过EntityManager:::warning在迁移中使用EntityManager虽然可行但不推荐它依赖的是当前检出的应用状态下的元数据而非迁移生成时的状态。当你的元数据随时间变化后老迁移可能因此出错。应优先在迁移中使用原始 SQL 查询。:::import { Migration } from mikro-orm/migrations; import { User } from ../entities/User; export class Migration20191019195930 extends Migration { async up(): Promisevoid { const em this.getEntityManager(); em.create(User, { ... }); await em.flush(); } }getEntityManager()会创建一个缓存的、且已绑定当前事务上下文的EntityManager实例见 Migration.ts因此通过它写入的数据与迁移本身处于同一事务。初始化迁移Initial migration该步骤是可选的仅在实体与 Schema 都已存在的特殊场景下需要。如果我们希望开始使用迁移但数据库 Schema 已经存在可以通过创建所谓的“初始化迁移”来启动初始化迁移只能在没有任何先前生成或执行过的迁移时创建。npx mikro-orm migration:create --initial该命令会创建包含schema:create命令 Schema dump 的初始化迁移且迁移会被自动标记为已执行。从源码看Migrator.createInitial()会先调用validateInitialMigration()做严格校验见 Migrator.ts若已有已执行或待执行的迁移抛出Initial migration cannot be created, as some migrations already exist若实体元数据为空且非 blank 模式抛出No entities found若数据库中已存在部分实体表但并非全部抛出Some tables already exist in your schema, remove them first to create the initial migration并列出冲突表名只有当数据库已包含全部实体对应的表时才认为初始化迁移已等效执行完毕将其自动记录为已执行。快照机制Snapshots创建新迁移时MikroORM 会自动把目标 Schema 快照保存到迁移文件夹中。之后再次创建迁移时会优先使用该快照而非当前数据库 Schema进行 diff。这意味着即使你在运行待执行迁移之前就尝试创建新迁移依然能得到正确的 Schema 差异。快照文件应当像普通迁移文件一样纳入版本控制。快照可通过配置migrations.snapshot: false关闭。从源码实现看快照文件的命名与位置由getSnapshotPath()决定见 Migrator.ts默认命名为.snapshot-dbName.json存放在以emit选项决定TS 模式下优先pathTs的迁移目录下内容为目标 Schema 的 JSON 序列化。创建迁移时Migrator.create()会调用storeCurrentSchema()写入快照checkSchema()与getSchemaDiff()则从快照读取目标 Schema 进行比对见 Migrator.ts。迁移配置自 v5 起使用umzug3.0原pattern选项已替换为glob。migrations.path与migrations.pathTs的工作方式与实体发现中的entities/entitiesTs一致。await MikroORM.init({ // default values: migrations: { tableName: mikro_orm_migrations, // 记录已执行迁移的数据库表名 path: ./migrations, // 迁移文件所在文件夹路径 pathTs: undefined, // TS 迁移文件路径若使用应将编译产物路径填入 path glob: !(*.d).{js,ts}, // 迁移文件匹配规则所有 .js 和 .ts 文件但不含 .d.ts transactional: true, // 每个迁移包裹在一个事务中 disableForeignKeys: true, // 以 set foreign_key_checks 0 或等效语句包裹 allOrNothing: true, // 将所有迁移包裹在主事务中 dropTables: true, // 是否允许删除表 safe: false, // 是否允许删除表和列 snapshot: true, // 创建新迁移时保存快照 emit: ts, // 迁移生成模式 generator: TSMigrationGenerator, // 迁移生成器可自定义格式 }, })配置项的源码级说明tableName默认mikro_orm_migrations。该表由 MigrationStorage.ts 按需自动创建包含id自增主键、name迁移名varchar与executed_at默认当前时间戳三列MigrationStorage.getMigrationName()会去掉.js/.ts扩展名后存储见 MigrationStorage.ts与文档“v5 起迁移不带扩展名存储”一致。transactionaltrue时 MigrationRunner.ts 会把迁移包在connection.transactional()中并把事务上下文通过setTransactionContext()注入迁移false时直接串行执行查询。注意若启用了运行时 Schemamigrations.schema或migrator.up({ schema })非事务迁移会直接报错见 MigrationRunner.ts。disableForeignKeys执行迁移时MigrationRunner.getQueries()会在迁移语句前后注入 Schema 开始/结束语句如set foreign_key_checks 0/1见 MigrationRunner.ts。allOrNothing决定是否用单个 master transaction 包裹全部迁移。从 CLI 实现看为了在 master transaction 外执行被标记的迁移需要第二条连接见 MigrationCommandFactory.ts 附近注释。emitts生成 TypeScript 迁移js/cjs生成 CommonJS JavaScript 迁移Migrator.getDefaultGenerator()依据该选项选择TSMigrationGenerator或JSMigrationGenerator见 Migrator.ts。glob迁移文件的匹配规则默认!(*.d).{js,ts}。生产环境运行迁移在生产环境我们通常希望使用编译后的迁移文件。自 v5 起这几乎开箱即用只需相应配置迁移路径import { MikroORM, Utils } from mikro-orm/core; await MikroORM.init({ migrations: { path: dist/migrations, pathTs: src/migrations, }, // or alternatively // migrations: { // path: Utils.detectTsNode() ? src/migrations : dist/migrations, // }, // ... });这样可以在 CLI通常启用了 TS 支持中生成 TS 迁移文件而在生产环境未注册 ts-node中使用编译后的 JS 文件。使用自定义MigrationGenerator生成新迁移时MigrationGenerator类负责生成文件内容。我们可以提供自己的实现例如格式化 SQL 语句import { TSMigrationGenerator } from mikro-orm/migrations; import { format } from sql-formatter; class CustomMigrationGenerator extends TSMigrationGenerator { generateMigrationFile(className: string, diff: { up: string[]; down: string[] }): string { const comment // this file was generated via custom migration generator\n\n; return comment super.generateMigrationFile(className, diff); } createStatement(sql: string, padLeft: number): string { sql format(sql, { language: postgresql }); // a bit of indenting magic sql sql.split(\n).map((l, i) i 0 ? l : ${ .repeat(padLeft 13)}${l}).join(\n); return super.createStatement(sql, padLeft); } } await MikroORM.init({ // ... migrations: { generator: CustomMigrationGenerator, }, });生成器的内部工作方式从 MigrationGenerator.ts 可以了解生成流程generate()先确定输出目录TS 模式下优先pathTs以当前时间戳生成className经namingStrategy.classToMigrationName(timestamp, name)文件名由fileName回调加上emit扩展名组成最终写入磁盘并返回[代码内容, 文件名]。TSMigrationGenerator.generateMigrationFile()生成的模板如下见 TSMigrationGenerator.ts头部导入Migration类名旁附带override name className稳定名称防止打包压缩器改写类名up()中逐条调用createStatement(sql, 4)生成this.addSql(...)语句仅当 diff 存在down语句时才生成down()方法。createStatement()会把 SQL 以模板字符串形式写入并转义反引号、$与反斜杠见 MigrationGenerator.ts。相应地JSMigrationGenerator生成 CommonJS 风格的require与exports代码见 JSMigrationGenerator.ts。通过 CLI 使用迁移npx mikro-orm migration:create # 基于当前 schema diff 创建新迁移 npx mikro-orm migration:up # 迁移到最新版本 npx mikro-orm migration:down # 向下迁移一步 npx mikro-orm migration:list # 列出所有已执行的迁移 npx mikro-orm migration:check # 检查 schema 是否是最新的 npx mikro-orm migration:pending # 列出所有待执行的迁移 npx mikro-orm migration:fresh # 删除数据库并迁移到最新版本要创建空白迁移文件可使用npx mikro-orm migration:create --blank。migration:up和migration:down命令支持--from-f、--to-t和--only-o选项以运行迁移的子集npx mikro-orm migration:up --from 2019101911 --to 2019102117 # 与上面等价 npx mikro-orm migration:up --only 2019101923 # 仅应用单个迁移 npx mikro-orm migration:down --to 0 # 向下迁移全部迁移要运行 TS 迁移文件需要在package.json中启用useTsNode标志参见安装与 CLI 工具配置。migration:fresh命令支持--seed选项在迁移完成后对数据库执行种子填充npx mikro-orm migration:fresh --seed # 使用默认 database seeder 填充 npx mikro-orm migration:fresh --seedUsersSeeder # 使用 UsersSeeder 填充可以在 ORM 配置中通过config.seeder.defaultSeeder指定默认 database seeder。此外从 MigrationCommandFactory.ts 的源码可以看到 CLI 还提供了migration:log将迁移标记为已执行但不运行、migration:unlog从已执行列表移除而不回滚与migration:rollup合并多个迁移等附加命令并支持--schema选项指定目标 SchemaPostgreSQL、MySQL、Oracle。编程式使用 Migrator也可以编写一个简单的脚本像这样初始化 MikroORMimport { MikroORM } from mikro-orm/core; (async () { const orm await MikroORM.init({ dbName: our-db-name, // ... }); const migrator orm.getMigrator(); await migrator.createMigration(); // creates file Migration20191019195930.ts await migrator.up(); // runs migrations up to the latest await migrator.up(name); // runs only given migration, up await migrator.up({ to: up-to-name }); // runs migrations up to given version await migrator.down(); // migrates one step down await migrator.down(name); // runs only given migration, down await migrator.down({ to: down-to-name }); // runs migrations down to given version await migrator.down({ to: 0 }); // migrates down to the first version await orm.close(true); })();然后通过ts-node运行该脚本或编译为纯 JS 后用node运行$ ts-node migrateMigrator还提供getPending()查询待执行迁移、checkSchema()通过快照对比判断 Schema 是否已过期返回布尔值等能力见 Migrator.ts。提供事务上下文某些场景下我们可能希望自己控制事务上下文await orm.em.transactional(async em { await migrator.up({ transaction: em.getTransactionContext() }); });此时migrator.up()会复用外层em.transactional()开启的事务迁移逻辑与外层业务代码处于同一事务。静态导入迁移如果我们不想动态导入文件夹例如使用 webpack 打包代码时可以直接导入迁移import { MikroORM } from mikro-orm/core; import { Migration20191019195930 } from ../migrations/Migration20191019195930.ts; await MikroORM.init({ migrations: { migrationsList: [ { name: Migration20191019195930.ts, class: Migration20191019195930, }, ], }, });借助 webpack 的 context module API我们可以动态导入迁移从而导入文件夹中的所有文件import { MikroORM } from mikro-orm/core; import { basename } from path; const migrations {}; function importAll(r) { r.keys().forEach( (key) (migrations[basename(key)] Object.values(r(key))[0]) ); } importAll(require.context(../migrations, false, /\.ts$/)); const migrationsList Object.keys(migrations).map((migrationName) ({ name: migrationName, class: migrations[migrationName], })); await MikroORM.init({ migrations: { migrationsList, }, });使用自定义迁移名称自 v5.7 起可通过--nameCLI 选项指定自定义迁移名称它会追加到生成的迁移名前缀之后# 生成文件 Migration20230421212713_add_email_property_to_user_table.ts npx mikro-orm migration:create --nameadd_email_property_to_user_table可以通过fileName回调自定义迁移文件的命名约定甚至用它强制迁移必须命名migrations: { fileName: (timestamp: string, name?: string) { // 强制用户提供名称否则会得到 Migration20230421212713_undefined if (!name) { throw new Error(Specify migration name via mikro-orm migration:create --name...); } return Migration${timestamp}_${name}; }, },:::caution 警告覆盖migrations.fileName策略时务必保证迁移文件名可排序绝不要让文件名以自定义name开头否则可能导致执行顺序错误。:::MongoDB 支持MongoDB 的迁移支持自 v5.3 起加入使用独立的mikro-orm/migrations-mongodb包且与现有 CLI 命令兼容。在迁移中可使用this.driver或this.getCollection()操作数据库。MongoDB 的Migration基类结构见 packages/migrations-mongodb/src/Migration.ts其ctx类型为TransactionClientSession提供getCollection(entityOrCollectionName)返回 mongodb 的Collection与getDb()返回Db两个辅助方法。事务Migrator的默认选项会使用事务这在 MongoDB 中会带来额外要求集合需要预先存在且需要运行副本集replicaset。你可能会希望为migrations: { transactional: false }关闭事务。使用事务时需要手动把事务上下文传给查询既可以通过 driver 方法的ctx选项也可以在this.getCollection()时通过 MongoDB 的session选项await this.driver.nativeDelete(Book, { foo: true }, { ctx: this.ctx });await this.getCollection(Book).updateMany({}, { $set: { updatedAt: new Date() } }, { session: this.ctx });MongoDB 迁移类示例import { Migration } from mikro-orm/migrations-mongodb; export class MigrationTest1 extends Migration { async up(): Promisevoid { // 使用 this.getCollection() 直接操作 mongodb collection await this.getCollection(Book).updateMany({}, { $set: { updatedAt: new Date() } }, { session: this.ctx }); // 或使用 this.driver 操作 MongoDriver API await this.driver.nativeDelete(Book, { foo: true }, { ctx: this.ctx }); } }已知限制LimitationsMySQLMySQL 无法回滚 DDL 变更这类查询会自动触发隐式提交implicit commit因此事务行为不符合预期参见 MySQL 官方文档的 implicit commit 说明。MongoDB不支持嵌套事务不支持 Schema diff 生成只生成空白迁移migration:create在 MongoDB 驱动下只会产出空迁移骨架需要手动编写迁移逻辑。小结MikroORM 的迁移体系围绕“实体元数据驱动的 Schema Diff 快照 主事务”三个支柱设计Migration基类提供统一的事务与查询上下文Migrator配合快照文件保证在任意时刻生成正确的 Schema 差异而MigrationStorage用一张mikro_orm_migrations表精确追踪执行状态。无论是通过 CLI 快速迭代、在 CI 中执行migration:check校验 Schema 一致性还是在生产环境用编译后的 JS 迁移配合pathTs优雅降级本文介绍的配置与源码细节都能帮助你把这套机制稳定地落地到实际项目中。赞分享后端【免费下载链接】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点击查看免费下载相关推荐HanLP部署指南从开发环境到生产环境迁移HanLP部署指南从开发环境到生产环境迁移 HanLP是针对中文优化的自然语言处理库提供词法分析、句法分析、命名实体识别等多种NLP功能适用于搭建文本挖掘人工智能NLP深度学习SSHFS技术深度解析构建企业级远程文件管理系统的3个核心策略SSHFS技术深度解析构建企业级远程文件管理系统的3个核心策略 在当今分布式计算环境中远程文件管理已成为技术团队面临的日常挑战。SSHFS作为基于SSH文件存储网络与通信Pomelo.EntityFrameworkCore.MySql部署实战从开发到生产环境的完整迁移指南Pomelo.EntityFrameworkCore.MySql部署实战从开发到生产环境的完整迁移指南 Pomelo.EntityFrameworkCore.上一篇终极Bash密码管理器指南pass与bash完美结合教程下一篇微信聊天记录永久保存指南如何让珍贵对话永不丢失创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
在 VS Code 中搭建 Git 源码开发调试环境:解读 contrib/vscode 一键初始化方案 版本控制开发工具CLI 【免费下载链接】git A fork of Git containing Windows-specific patches. 项目地址: https://gitcode.com/gh_mirrors/git/git 点击查看 免费下载 导读
本文围绕 Git 仓库中 contrib/vscode/README.md 及其配套脚本 contrib/vscode/init.sh… · 2026/9/25 3:27:07
洛阳格力工厂游学:从产线细节读懂智能制造与精益生产 2026年一开年,我就给自己安排了一趟特别的外出——跟着本地一个制造业协会的游学团,走进了洛阳格力工厂。这一趟下来,最大的感受是:我们平时聊智能制造、工业4.0、精益生产,聊得再多,也不如去产线边上站二十… · 2026/9/25 3:27:01
Word页脚总页数减1:NUMPAGES域代码修改与公式域嵌套实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:26:55
MCP服务发展现状的有趣发现:从stdio到Streamable HTTP,TaoToken统一Key接入实测 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:26:02
SOAP 规范实战:用 XML+HTTP 搭一套可调试的 RPC 骨架,并接入 TaoToken 统一 Key /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:56
深入gnhf编排器架构:状态机如何让AI代理整夜循环不丢一行代码 深入gnhf编排器架构:状态机如何让AI代理整夜循环不丢一行代码 【免费下载链接】gnhf Before I go to bed, I tell my agents: good night, have fun 项目地址: https://gitcode.com/gh_mirrors/gn/gnhf
gnhf(good night, have fun)是一… · 2026/9/25 4:25:44
VirtualBox E_FAIL (0x80004005) 报错全解析:从驱动冲突到UUID修复 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:44
MIPI DSI转LVDS桥接方案:LT9211与N76E003配置实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:44
Windows 11锁屏机制深度解析与分版本禁用方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:25:44
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37