Mikro-ORM中如何创建关联已有模型关系的Factory
MikroORM Factory 关联定义实现方案
你遇到的关联赋值undefined报错,核心原因是each传入的异步回调没有等待执行完成,实体实例生成时关联字段还没完成赋值,同时旧写法里存在重复查库、重复声明变量的问题,以下是两种可直接落地的实现方式:
方案1:Seeder层提前初始化关联(兼容所有版本)
不需要修改Factory内部代码,提前在seeder里查好/创建好需要的关联实体,避免循环内重复查库,同时去掉each里的异步逻辑,就不会出现时序问题:
export class DatabaseSeeder extends Seeder { async run(em: EntityManager): Promise<void> { // 提前初始化公共关联,仅执行一次数据库查询 let userType = await em.findOne(UserType, 1); if (!userType) { userType = em.create(UserType, { type: 'test' }); } // 用create替代make,生成实例的同时自动标记持久化 const users = await new UserFactory(em) .each(user => { user.type = userType; }) .create(10); } }
方案2:Factory内部直接定义关联逻辑(推荐,MikroORM v5+支持)
v5及以上版本的Factory基类中,em属性是protected修饰的,子类可以直接访问,直接把关联逻辑写在definition方法里即可,注意异步查询需要把definition改成async方法:
import { Factory, Faker } from '@mikro-orm/seeder'; import { User, UserType } from './entities'; export class UserFactory extends Factory<User> { model = User; async definition(faker: Faker): Promise<Partial<User>> { let userType = await this.em.findOne(UserType, 1); if (!userType) { userType = this.em.create(UserType, { type: 'test' }); } return { firstName: faker.person.firstName(), lastName: faker.person.lastName(), type: userType }; } }
注意:Faker v8+版本中姓名相关API已迁移至
faker.person命名空间,旧的faker.name.firstName()写法已废弃,使用时注意对应版本。
原写法的问题说明
each中使用async回调但未等待执行,make()执行时关联赋值逻辑还没跑完,导致字段为undefined- 循环内重复查询id=1的UserType,产生不必要的数据库开销
- 重复声明
userType变量属于语法错误,代码中还打印了未定义的tenant变量 make()方法仅生成实体实例不会自动持久化,需要入库的场景直接用create()方法更便捷。
内容的提问来源于stack exchange,提问作者Young L.
相关产品推荐
相关产品推荐

