Skip to main content
Version: Next

Using Multiple Schemas

In MySQL and PostgreSQL it is possible to define your entities in multiple schemas. In MySQL terminology, it is called database, but from an implementation point of view, it is a schema.

To use multiple schemas, your connection needs to have access to all of them (multiple connections are not supported in a single MikroORM instance).

All you need to do is simply define the schema name via schema options, or table name including schema name in tableName option:

@Entity({ schema: 'first_schema' })
export class Foo { ... }

// or alternatively we can specify it inside custom table name
@Entity({ tableName: 'second_schema.bar' })
export class Bar { ... }

Then use those entities as usual. Resulting SQL queries will use this tableName value as a table name so as long as your connection has access to given schema, everything should work as expected.

You can also query for entity in specific schema via EntityManager, EntityRepository or QueryBuilder:

const user = await em.findOne(User, { ... }, { schema: 'client-123' });

To create entity in specific schema, you will need to use QueryBuilder:

const qb = em.createQueryBuilder(User);
await qb.insert({ email: 'foo@bar.com' }).withSchema('client-123');

Default schema on EntityManager

Instead of defining schema per entity or operation it's possible to .fork() EntityManger and define a default schema that will be used with wildcard schemas.

const fork = em.fork({ schema: 'client-123' });
await fork.findOne(User, { ... });

// Will yield the same result as
const user = await em.findOne(User, { ... }, { schema: 'client-123' });

When creating an entity the fork will set default schema

const fork = em.fork({ schema: 'client-123' });
const user = new User();
user.email = 'foo@bar.com';
await fork.persist(user).flush();

// Will yield the same result as
const qb = em.createQueryBuilder(User);
await qb.insert({ email: 'foo@bar.com' }).withSchema('client-123');

You can also set or clear schema

em.schema = 'client-123';
const fork = em.fork({ schema: 'client-1234' });
fork.schema = null;

EntityManager.schema Respects the context, so global EM will give you the contextual schema if executed inside request context handler

Wildcard Schema

Since v5, MikroORM also supports defining entities that can exist in multiple schemas. To do that, we just specify wildcard schema:

@Entity({ schema: '*' })
export class Book {

@PrimaryKey()
id!: number;

@Property({ nullable: true })
name?: string;

@ManyToOne(() => Author, { nullable: true, deleteRule: 'cascade' })
author?: Author;

@ManyToOne(() => Book, { nullable: true })
basedOn?: Book;

}

Entities like this will be by default ignored when using SchemaGenerator, as we need to specify which schema to use. For that we need to use the schema option of the createSchema/updateSchema/dropSchema methods or the --schema CLI parameter.

On runtime, the wildcard schema will be replaced with either FindOptions.schema, EntityManager.schema or with the schema option from the ORM config.

Note about migrations

Currently, this is not supported via migrations, they will always ignore wildcard schema entities, and SchemaGenerator needs to be used explicitly. Given the dynamic nature of such entities, it makes sense to only sync the schema dynamically, e.g. in an API endpoint. We could still use the ORM migrations, but we need to add the dynamic schema queries manually to migration files. It makes sense to use the safe mode for such queries.