Multi-ORM Entities
How to define database entities in Ever Gauzy using the shared Multi-ORM decorator system for compatibility with both TypeORM and MikroORM.
Entity Definition Patternโ
All entities use Multi-ORM decorators that generate metadata for both TypeORM and MikroORM:
import {
MultiORMEntity,
MultiORMColumn,
MultiORMManyToOne,
MultiORMOneToMany,
MultiORMManyToMany,
} from "@gauzy/core";
import { TenantOrganizationBaseEntity } from "@gauzy/core";
@MultiORMEntity("employee")
export class Employee extends TenantOrganizationBaseEntity {
// Simple columns
@MultiORMColumn()
firstName: string;
@MultiORMColumn()
lastName: string;
@MultiORMColumn({ nullable: true })
billRateValue?: number;
@MultiORMColumn({ nullable: true, type: "varchar" })
billRateCurrency?: string;
@MultiORMColumn({ nullable: true })
startedWorkOn?: Date;
@MultiORMColumn({ default: true })
isActive: boolean;
// Relations
@MultiORMManyToOne(() => User, { nullable: false, onDelete: "CASCADE" })
user: IUser;
@MultiORMColumn({ relationId: true })
userId: string;
@MultiORMOneToMany(() => TimeLog, (timeLog) => timeLog.employee)
timeLogs?: ITimeLog[];
@MultiORMManyToMany(() => OrganizationProject, (project) => project.members)
projects?: IOrganizationProject[];
}
Base Entity Classesโ
Choosing the Right Base Classโ
| Base Class | Fields Provided | Use When |
|---|---|---|
BaseEntity | id, createdAt, updatedAt, isActive, isArchived | Non-tenant entities |
TenantBaseEntity | + tenantId, tenant | Tenant-scoped, no organization |
TenantOrganizationBaseEntity | + organizationId, organization | Most entities |
BaseEntityโ
export abstract class BaseEntity {
@MultiORMColumn({ primary: true })
id: string;
@MultiORMColumn({ createDate: true })
createdAt: Date;
@MultiORMColumn({ updateDate: true })
updatedAt: Date;
@MultiORMColumn({ nullable: true, default: true })
isActive?: boolean;
@MultiORMColumn({ nullable: true, default: false })
isArchived?: boolean;
}
TenantBaseEntityโ
export abstract class TenantBaseEntity extends BaseEntity {
@MultiORMManyToOne(() => Tenant, { nullable: false })
tenant: ITenant;
@MultiORMColumn({ relationId: true })
tenantId: string;
}
TenantOrganizationBaseEntityโ
export abstract class TenantOrganizationBaseEntity extends TenantBaseEntity {
@MultiORMManyToOne(() => Organization, { nullable: true })
organization?: IOrganization;
@MultiORMColumn({ relationId: true, nullable: true })
organizationId?: string;
}
Column Typesโ
Basic Column Optionsโ
// String
@MultiORMColumn()
name: string;
// Number
@MultiORMColumn({ type: 'numeric' })
amount: number;
// Boolean with default
@MultiORMColumn({ default: true })
isActive: boolean;
// Nullable
@MultiORMColumn({ nullable: true })
description?: string;
// Date
@MultiORMColumn({ nullable: true })
startDate?: Date;
// Enum
@MultiORMColumn({ type: 'varchar' })
status: StatusEnum;
// JSON/JSONB
@MultiORMColumn({ type: 'jsonb', nullable: true })
metadata?: Record<string, any>;
// Text (long content)
@MultiORMColumn({ type: 'text', nullable: true })
content?: string;
Relation Typesโ
ManyToOneโ
// Required relation
@MultiORMManyToOne(() => User, { nullable: false, onDelete: 'CASCADE' })
user: IUser;
@MultiORMColumn({ relationId: true })
userId: string;
// Optional relation
@MultiORMManyToOne(() => OrganizationProject, { nullable: true })
project?: IOrganizationProject;
@MultiORMColumn({ relationId: true, nullable: true })
projectId?: string;
OneToManyโ
@MultiORMOneToMany(() => TimeLog, (timeLog) => timeLog.employee)
timeLogs?: ITimeLog[];
ManyToManyโ
// With join table
@MultiORMManyToMany(() => Tag, (tag) => tag.employees)
@JoinTable({ name: 'tag_employee' })
tags?: ITag[];
// Without join table (inverse side)
@MultiORMManyToMany(() => OrganizationProject, (project) => project.members)
projects?: IOrganizationProject[];
OneToOneโ
@MultiORMOneToOne(() => EmployeeSettings, (settings) => settings.employee)
settings?: IEmployeeSettings;
Contract Interfacesโ
Every entity has a corresponding interface in @gauzy/contracts:
// packages/contracts/src/employee.model.ts
export interface IEmployee extends IBasePerTenantAndOrganizationEntityModel {
firstName: string;
lastName: string;
billRateValue?: number;
billRateCurrency?: string;
startedWorkOn?: Date;
isActive: boolean;
userId: string;
user?: IUser;
timeLogs?: ITimeLog[];
projects?: IOrganizationProject[];
}
The entity class implements the contract interface:
@MultiORMEntity("employee")
export class Employee
extends TenantOrganizationBaseEntity
implements IEmployee {
// ...
}
Best Practicesโ
DOโ
- โ
Always extend a
BaseEntitysubclass - โ
Use
MultiORM*decorators, not raw TypeORM/MikroORM decorators - โ
Define a contract interface in
@gauzy/contracts - โ
Include
relationIdcolumns for all relations - โ
Add
nullable: truefor optional fields
DON'Tโ
- โ Import decorators directly from
typeormor@mikro-orm/core - โ Use TypeORM-specific features like
@Tree()without Multi-ORM support - โ Create entities without tenant scoping (unless intentionally cross-tenant)
- โ Use
enumcolumn type directly (usevarcharwith TypeScript enum)
Related Pagesโ
- Multi-ORM Architecture โ architecture overview
- TypeORM Setup โ TypeORM specifics
- MikroORM Setup โ MikroORM specifics
- Tenant Filtering โ tenant scoping rules