Multi-ORM Deep Dive
Writing queries that work across TypeORM and MikroORM in Ever Gauzy.
Why Multi-ORM?โ
Gauzy supports both TypeORM and MikroORM through the MultiORM decorator system. This allows:
- TypeORM โ mature, widely used, great for PostgreSQL
- MikroORM โ modern, identity map, unit-of-work pattern
The active ORM is determined by the DB_ORM environment variable.
Entity Decoratorsโ
MultiORMEntityโ
@MultiORMEntity("employee", {
mikroOrmRepository: () => MikroOrmEmployeeRepository,
})
export class Employee extends TenantOrganizationBaseEntity {
@MultiORMColumn()
name: string;
@MultiORMColumn({ nullable: true })
description?: string;
}
Relation Decoratorsโ
// Many-to-One
@MultiORMManyToOne(() => Organization, { nullable: true })
@JoinColumn()
organization?: Organization;
// One-to-Many
@MultiORMOneToMany(() => Task, (task) => task.creator)
createdTasks?: Task[];
// Many-to-Many
@MultiORMManyToMany(() => Tag, (tag) => tag.employees)
tags?: Tag[];
Query Patternsโ
Using CrudServiceโ
Most queries go through TenantAwareCrudService:
// Find all with filters
const result = await this.service.findAll({
where: { status: "active" },
relations: ["user", "teams"],
order: { createdAt: "DESC" },
});
// Find one by ID
const employee = await this.service.findOneByIdString(id, {
relations: ["user"],
});
Repository Patternโ
For complex queries, inject repositories:
@Injectable()
export class MyService {
constructor(
@InjectRepository(MyEntity)
private readonly repository: Repository<MyEntity>,
) {}
}
Conditional ORM Logicโ
When you need ORM-specific behavior:
if (isTypeORM()) {
// TypeORM-specific query builder
const qb = this.repository.createQueryBuilder("entity");
} else {
// MikroORM-specific entity manager
const em = this.entityManager;
}
Related Pagesโ
- Core Entities โ entity definitions
- Architecture Overview โ system architecture