Defining Entities
Entities are simple javascript objects (so called POJO). No real restrictions are made, no need to extend any base class, using entity constructors is working as well - they are never executed for managed entities (loaded from database). Every entity is required to have a primary key.
There are two ways how you can define your entities:
- Decorated classes - the attributes of the entity as well as each property are provided
via decorators. We use
@Entity()
decorator on the class. Entity properties are decorated either with@Property
decorator, or with one of reference decorators:@ManyToOne
,@OneToMany
,@OneToOne
and@ManyToMany
. Check out the full decorator reference. EntitySchema
helper - WithEntitySchema
helper we define the schema programmatically. We can use regular classes as well as interfaces. This approach also allows to re-use partial entity definitions (e.g. traits/mixins). Read more about this in Defining Entities via EntitySchema section.
Moreover, how the metadata extraction from decorators happens is controlled
via MetadataProvider
. Two main metadata providers are:
ReflectMetadataProvider
- usesreflect-metadata
to read the property types. Faster but simpler and more verbose.TsMorphMetadataProvider
- usests-morph
to read the type information from the TypeScript compiled API. Heavier (requires full TS as a dependency), but allows DRY entity definition. Withts-morph
we are able to extract the type as it is defined in the code, including interface names, as well as optionality of properties.
Read more about them in the Metadata Providers section.
Current set of decorators in MikroORM is designed to work with the
tsc
. Usingbabel
is also possible, but requires some additional setup. Read more about it here. For notes aboutwebpack
, read the deployment section.
ts-morph
is compatible only with thetsc
approach.
From v3 you can also use default exports when defining your entity.
Example definition of a Book
entity follows. We can switch the tabs to see the difference
for various ways:
- reflect-metadata
- ts-morph
- EntitySchema
Here is another example of Author
entity, that was referenced from the Book
one, this
time defined for mongo:
- reflect-metadata
- ts-morph
- EntitySchema
More information about modelling relationships can be found on modelling relationships page.
For an example of Vanilla JavaScript usage, take a look here.
#
Optional PropertiesWith the default reflect-metadata
provider, we need to mark each optional property as nullable: true
.
When using ts-morph
, if you define the property as optional (marked with ?
), this will be automatically considered
as nullable property (mainly for SQL schema generator).
- reflect-metadata
- ts-morph
- EntitySchema
#
Default valuesWe can set default value of a property in 2 ways:
- Use runtime default value of the property. This approach should be preferred as long
as we are not using any native database function like
now()
. With this approach our entities will have the default value set even before it is actually persisted into the database (e.g. when we instantiate new entity vianew Author()
orem.create(Author, { ... })
.
- reflect-metadata
- ts-morph
- EntitySchema
- Use
default
parameter of@Property
decorator. This way the actual default value will be provided by the database, and automatically mapped to the entity property after it is being persisted (after flush). To use SQL functions likenow()
, usedefaultRaw
.
Since v4 you should use
defaultRaw
for SQL functions, asdefault
with string values will be automatically quoted.
- reflect-metadata
- ts-morph
- EntitySchema
#
EnumsTo define enum property, use @Enum()
decorator. Enums can be either numeric or string valued.
For schema generator to work properly in case of string enums, we need to define the enum is same file as where it is used, so its values can be automatically discovered. If we want to define the enum in another file, we should reexport it also in place where we use it.
Another possibility is to provide the reference to the enum implementation in the decorator
via @Enum(() => UserRole)
.
You can also set enum items manually via
items: string[]
attribute.
- reflect-metadata
- ts-morph
- EntitySchema
#
Enum arraysWe can also use array of values for enum, in that case, EnumArrayType
type
will be used automatically, that will validate items on flush.
- reflect-metadata
- ts-morph
- EntitySchema
#
Mapping directly to primary keysSometimes we might want to work only with the primary key of a relation.
To do that, we can use mapToPk
option on M:1 and 1:1 relations:
- reflect-metadata
- ts-morph
- EntitySchema
For composite keys, this will give us ordered tuple representing the raw PKs, which is the internal format of composite PK:
- reflect-metadata
- ts-morph
- EntitySchema
#
Formulas@Formula()
decorator can be used to map some SQL snippet to your entity.
The SQL fragment can be as complex as you want and even include subselects.
- reflect-metadata
- ts-morph
- EntitySchema
Formulas will be added to the select clause automatically. In case you are facing
problems with NonUniqueFieldNameException
, you can define the formula as a
callback that will receive the entity alias in the parameter:
- reflect-metadata
- ts-morph
- EntitySchema
#
IndexesYou can define indexes via @Index()
decorator, for unique indexes, use @Unique()
decorator.
You can use it either on entity class, or on entity property:
- reflect-metadata
- ts-morph
- EntitySchema
#
Custom TypesYou can define custom types by extending Type
abstract class. It has 4 optional methods:
convertToDatabaseValue(value: any, platform: Platform): any
Converts a value from its JS representation to its database representation of this type.
convertToJSValue(value: any, platform: Platform): any
Converts a value from its database representation to its JS representation of this type.
toJSON(value: any, platform: Platform): any
Converts a value from its JS representation to its serialized JSON form of this type. By default converts to the database value.
getColumnType(prop: EntityProperty, platform: Platform): string
Gets the SQL declaration snippet for a field of this type.
More information can be found in Custom Types section.
#
Lazy scalar propertiesYou can mark any property as lazy: true
to omit it from the select clause.
This can be handy for properties that are too large and you want to have them
available only some times, like a full text of an article.
- reflect-metadata
- ts-morph
- EntitySchema
You can use populate
parameter to load them.
If the entity is already loaded and you need to populate a lazy scalar property, you might need to pass
refresh: true
in theFindOptions
.
#
Virtual PropertiesYou can define your properties as virtual, either as a method, or via JavaScript get/set
.
Following example defines User entity with firstName
and lastName
database fields, that
are both hidden from the serialized response, replaced with virtual properties fullName
(defined as a classic method) and fullName2
(defined as a JavaScript getter).
For JavaScript getter you need to provide
{ persist: false }
option otherwise the value would be stored in the database.
- reflect-metadata
- ts-morph
- EntitySchema
#
Entity file namesStarting with MikroORM 4.2, there is no limitation for entity file names. It is now also possible to define multiple entities in a single file using folder based discovery.
#
Using BaseEntityYou can define your own base entity with properties that you require on all entities, like primary key and created/updated time. Single table inheritance is also supported.
Read more about this topic in Inheritance Mapping section.
If you are initializing the ORM via
entities
option, you need to specify all your base entities as well.
- reflect-metadata
- ts-morph
- EntitySchema
There is a special case, when we need to annotate the base entity - if we are using folder based discovery, and the base entity is not using any decorators (e.g. it does not define any decorated property). In that case, we need to mark it as abstract:
#
Examples of entity definition with various primary keys#
Using id as primary key (SQL drivers)- reflect-metadata
- ts-morph
- EntitySchema
#
Using UUID as primary key (SQL drivers)- reflect-metadata
- ts-morph
- EntitySchema
uuid-osp module function as primary key#
Using PostgreSQLRequires enabling the module via: create extension "uuid-ossp";
- reflect-metadata
- ts-morph
- EntitySchema
#
Using BigInt as primary key (MySQL and PostgreSQL)You can use BigIntType
to support bigint
s. By default, it will represent the value as
a string
.
- reflect-metadata
- ts-morph
- EntitySchema
If you want to use native bigint
s, read the following guide: Using native BigInt PKs.
#
Example of Mongo entity- reflect-metadata
- ts-morph
- EntitySchema
#
Using MikroORM's BaseEntity (previously WrappedEntity)From v4 BaseEntity
class is provided with init
, isInitialized
, assign
and other methods that are otherwise available via the wrap()
helper.
Usage of the
BaseEntity
is optional.
With your entities set up, you can start using entity manager and repositories as described in following sections.