后端【免费下载链接】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 的多 Schema 支持展开讲解在 MySQL、PostgreSQL 等数据库中如何通过schema选项、tableName前缀、EntityManager默认 Schema 与QueryBuilder.withSchema()在多个 Schema 之间切换查询与写入并深入剖析 v5 引入的通配符 Schemaschema: *在多租户场景下的工作原理及其与SchemaGenerator、Migrations 的协作边界。读完本文你将掌握从静态多 Schema 建模到运行时动态切换 Schema的完整实战方案。一、什么是多 SchemaMySQL 与 PostgreSQL 的差异在 MySQL 和 PostgreSQL 中实体可以定义在多个 Schema 中。MySQL 术语里通常称之为数据库database但从实现角度看它就是 Schema。MikroORM 在 SQL 方言层统一抽象了Schema这一概念因此两套数据库在使用方式上完全一致。使用多 Schema 的前提条件非常关键连接connection必须能够访问所有 Schema单个 MikroORM 实例不支持多个连接。这意味着你不需要也不能为每个 Schema 单独初始化一个 ORM 实例而是由同一个连接、同一个实体元数据在运行时决定 SQL 落到哪个 Schema。这一约束在源码层面贯穿始终ConnectionOptions中只有一个可选的默认schema字段见 Configuration.ts后续所有 Schema 切换都发生在查询执行层。二、在实体定义阶段指定 Schema定义实体时有两种等价方式告诉 MikroORM 该实体属于哪个 SchemaEntity({ schema: first_schema }) export class Foo { ... } // 或者将 schema 名拼进自定义表名 Entity({ tableName: second_schema.bar }) export class Bar { ... }两种方式最终殊途同归生成的 SQL 会直接使用带 Schema 前缀的完整表名如second_schema.bar。只要连接拥有对应 Schema 的访问权限查询、插入、更新、删除以及关系加载都会正常工作业务代码无需感知 Schema 的存在。三、查询时按操作指定 Schema除了在实体定义时写死 Schema你还可以在每次查询时动态指定 Schema三个入口均支持EntityManagerem.findOne(User, {...}, { schema: client-123 })EntityRepository同样在 FindOptions 中传入schemaQueryBuilderqb.withSchema(client-123)典型的场景是同一实体、多个租户/客户分库实体定义保持一份运行时按登录用户的上下文传入不同的 Schema 名。FindOptions.schema是运行时优先级最高的 Schema 来源之一另一来源是EntityManager.schema与 ORM 配置中的schema后文通配符 Schema 一节会详细说明这三者的替换顺序。四、写入指定 SchemaQueryBuilder.withSchema()与查询不同通过EntityManager的常规persist流程创建实体时实体落库的 Schema 由实体元数据决定。要在写入时动态指定 Schema需要显式使用QueryBuilderconst qb em.createQueryBuilder(User); await qb.insert({ email: foobar.com }).withSchema(client-123);withSchema()的底层实现非常直接它把 Schema 存入查询构建器的内部状态后续生成 SQL 时据此限定表名。对应实现见 QueryBuilder.tswithSchema(schema?: string): this { this.ensureNotFinalized(); this.#state.schema schema; return this; }注意ensureNotFinalized()的存在一旦查询被 finalize例如已执行或已拼接就不能再修改 Schema这与offset、setLockMode等链式方法的保护机制一致。五、EntityManager 默认 Schemafork 与上下文感知如果每个操作都要手动传schema过于繁琐可以对EntityManager执行.fork()并指定默认 Schema此后该 fork 上的所有操作都会自动落到该 Schemaconst fork em.fork({ schema: client-123 }); await fork.findOne(User, { ... }); // 等价于 const user await em.findOne(User, { ... }, { schema: client-123 });创建实体时同样生效——fork 会将默认 Schema 应用到新实体的写入const fork em.fork({ schema: client-123 }); const user new User(); user.email foobar.com; await fork.persistAndFlush(user); // 等价于 const qb em.createQueryBuilder(User); await qb.insert({ email: foobar.com }).withSchema(client-123);默认 Schema 也可以在 fork 之后随时设置或清除em.schema client-123; const fork em.fork({ schema: client-1234 }); fork.schema null; // 清除默认 Schema回退到实体/配置定义这里有一个值得注意的实现细节EntityManager.schema的 getter/setter 是**上下文感知context-aware**的。源码见 EntityManager.tsget schema(): string | undefined { return this.getContext(false).#schema; } set schema(schema: string | null | undefined) { this.getContext(false).#schema schema ?? undefined; }getContext(false)意味着当代码运行在 RequestContext 处理器 内部时全局的em.schema读写会透明地落到当前请求上下文的 fork 上从而实现每个请求一个 Schema、全局代码零侵入的多租户隔离模式。六、通配符 Schema一个实体对应多套 Schema自 v5 起MikroORM 支持定义可存在于多个 Schema的实体——只要把schema写成通配符*Entity({ schema: * }) export class Book { PrimaryKey() id!: number; Property({ nullable: true }) name?: string; ManyToOne(() Author, { nullable: true, onDelete: cascade }) author?: Author; ManyToOne(() Book, { nullable: true }) basedOn?: Book; }通配符 Schema 实体是典型的多租户建模方案每个租户拥有结构完全相同的独立 Schema如client-1、client-2、client-3而实体定义只有一份。运行时通配符会被替换为以下三处之一按优先级FindOptions.schema单次查询指定EntityManager.schemafork 或em.schema设置ORM 配置ConnectionOptions.schema默认兜底。替换逻辑发生在 SQL 生成阶段因此查询、加载关系、级联删除如示例中的onDelete: cascade都会自动落到目标 Schema。6.1 SchemaGenerator 与 CLI --schema通配符 Schema 实体默认会被SchemaGenerator忽略因为生成器不知道要为哪个 Schema 建表。需要显式指定目标 Schema编程方式createSchema/updateSchema/dropSchema方法传入schema选项CLI 方式npx mikro-orm schema:create --schema client-123等命令的--schema参数。这一行为在源码中有明确印证SqlSchemaGenerator会收集所有schema *的元数据并将其表名放入排除列表只有传入includeWildcardSchema时才跳过该剪枝逻辑。见 SqlSchemaGenerator.tsconst wildcardSchemaTables options.includeWildcardSchema ? [] : [...this.metadata.getAll().values()].filter(meta meta.schema *).map(meta meta.tableName); fromSchema.prune(options.schema, wildcardSchemaTables); toSchema.prune(options.schema, wildcardSchemaTables);也就是说不带includeWildcardSchema时通配符实体被从 diff 的 from/to 两端剪除避免对未指定 Schema 的实体生成误操作。6.2 关于 Migrations 的注意事项当前版本中通配符 Schema 实体无法直接通过 Migrations 管理Migrations 会始终忽略通配符 Schema 实体必须显式使用SchemaGenerator。考虑到这类实体的动态特性新租户随时可能被创建合理的实践是在 API 端点中动态同步 Schema例如注册新租户时调用SchemaGenerator为该租户建表仍然保留 ORM Migrations 管理普通实体但将动态 Schema 的建表 SQL手动写入迁移文件对这类动态查询建议开启safe模式safe: true避免破坏性操作在误判场景下造成数据损失。七、整体工作流从静态定义到动态切换综合以上内容一套完整的多 Schema 工作流可以概括为静态多 Schema实体用schema或tableName前缀固定归属连接需有全部 Schema 权限运行时查询切换FindOptions.schema单次或em.fork({ schema })/em.schema会话级运行时写入切换QueryBuilder.withSchema()显式插入目标 Schema多租户动态 Schema实体声明schema: *结合RequestContext按请求解析实际 Schema建表通过SchemaGenerator--schema参数按需同步迁移文件手动补充动态 SQL。其中第 4 步与请求上下文配合时EntityManager.schema的上下文感知 getter/setter 是关键枢纽全局代码无需改动每个请求通过 RequestContext 自动获得各自的 Schema 隔离。八、源码路径速查能力点源码位置QueryBuilder.withSchema()状态写入QueryBuilder.tsEntityManager.schema上下文感知读写EntityManager.ts连接默认 Schema 配置项Configuration.tsSchemaGenerator 通配符实体剪枝SqlSchemaGenerator.ts关联文档multiple-schemas.md、identity-map.md、migrations.md如需深入了解 Schema 与数据库连接的配置细节可继续阅读 configuration.md 与 schema-generator.md 两篇指南。赞分享后端【免费下载链接】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 多 Schema 使用完全指南多数据库架构、通配符 Schema 与 SQLite ATTACH DATABASE 实战MikroORM 多 Schema 使用完全指南多数据库架构、通配符 Schema 与 SQLite ATTACH DATABASE 实战 在 MySQL、P后端io-ts与JSON Schema如何将运行时类型转换为JSON Schema定义io ts与JSON Schema如何将运行时类型转换为JSON Schema定义 想要在TypeScript项目中实现运行时类型安全同时生成标准的JSON后端PostgREST Schema 暴露与多租户切换完全指南db-schemas、Profile 头与动态 SchemaPostgREST Schema 暴露与多租户切换完全指南db schemas、Profile 头与动态 Schema 导读 本文基于 PostgREST 官后端API网关上一篇智慧教育平台电子课本解析工具让教材获取变得前所未有的简单下一篇如何永久保存微信聊天记录5步掌握你的数字记忆宝库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考