MikroORM 入门:TypeScript 的现代 DataMapper ORM

MikroORM 是基于 DataMapper 模式的 TS ORM:实体即类、类型安全、支持 SQL 与 MongoDB。本文走完实体定义、增删改查与关联管理全流程。

最佳实践
事件循环与异步任务流转插画

MikroORM 用装饰器定义实体类,em.persist() 收集变更、em.flush() 统一落库——Unit of Work 模式让批量操作与事务天然一体。它在"类型安全 ORM"光谱上比 TypeORM 更现代、比 Prisma 更接近经典 ORM 语义。

MikroORM 的定位

TypeScript 一等公民、DataMapper + Unit of Work 模式、SQL(PostgreSQL/MySQL/SQLite)与 MongoDB 双支持。实体是普通 TS 类(装饰器标注映射),业务逻辑与数据库操作解耦——经典 ORM 的正统路线,现代化实现。

初始化与实体定义

npm install @mikro-orm/core @mikro-orm/sqlite reflect-metadata
import { Entity, PrimaryKey, Property } from '@mikro-orm/core';

@Entity()
export class User {
  @PrimaryKey()
  id!: number;

  @Property()
  name!: string;

  @Property({ unique: true })
  email!: string;

  @Property({ nullable: true })
  age?: number;

  @Property()
  createdAt: Date = new Date();
}
import { MikroORM } from '@mikro-orm/sqlite';

const orm = await MikroORM.init({
  dbName: './app.db',
  entities: [User],
});
await orm.schema.createSchema();  // 建表
const em = orm.em.fork();         // EntityManager:所有操作的入口

插入数据

const user = new User();
user.name = '张三';
user.email = 'zhang@example.com';
user.age = 28;

em.persist(user);
await em.flush();   // 此刻才真正执行 INSERT

Unit of Work 要点:persist 只是"登记",flush 统一提交——一次 flush 内的多个变更自动包事务,中间失败全部回滚。

查询

// 主键查询
const user = await em.findOne(User, 1);

// 条件查询(类型安全)
const adults = await em.find(User, { age: { $gte: 18 } }, {
  orderBy: { age: 'desc' },
  limit: 10,
});

// 关联加载
const posts = await em.find(Post, { published: true }, { populate: ['author'] });

查询条件的键与值全部类型检查——em.find(User, { nmae: 'x' }) 编译期报错。

更新与删除

// 更新:查出实体 → 改属性 → flush
const user = await em.findOneOrFail(User, 1);
user.age = 29;
await em.flush();   // 脏检查自动生成 UPDATE

// 删除
const target = await em.findOneOrFail(User, 2);
em.remove(target);
await em.flush();

脏检查(change detection)是 Unit of Work 的精髓:你只管改对象,ORM 计算出最小 UPDATE 语句。

关联与级联

一对多/多对多靠装饰器声明(@OneToMany、@ManyToOne、@ManyToMany),级联持久化(cascade persist)让"存用户连同地址一起存"成为默认行为。populate 选项控制关联加载时机,避免 N+1。

用实际查询验证数据访问方案

MikroORM 入门的选择最终要落到查询次数、SQL 耗时与连接占用。应用接入观测云 APM 时,先核对 SDK 是否支持实际使用的数据库驱动,不能因为使用了某个 ORM 就假设全部查询自动可见。未覆盖的查询可手动插桩;PostgreSQL 等服务端数据库另配实例采集。SQL 和绑定参数上报前须脱敏,再按相同接口比较 N+1 查询与慢查询的变化。

接入文档:Node.js APM 接入 · PostgreSQL 采集 · 日志采集。

常见问题(FAQ)

Q:MikroORM 和 TypeORM 怎么选?

TypeORM 的 ActiveRecord 路线与历史包袱较重;MikroORM 的 DataMapper + Unit of Work 更严谨,TS 类型支持与文档质量更好。新项目两者之间选 MikroORM。

Q:EntityManager 为什么要 fork?

全局共享一个 em 会导致身份映射(identity map)污染——Web 应用中每个请求 fork 一个独立 em,请求结束即弃。NestJS 集成包已自动化此模式。

Q:生产迁移怎么管理?

MikroORM 自带迁移系统:npx mikro-orm migration:create 从实体差异生成迁移,CI 中 migration:up 执行。实体即单一事实源。


参考文档

本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台