MikroORM uses the Identity Map pattern to track objects. Whenever you fetch an object from
the database, MikroORM will keep a reference to this object inside its
This allows MikroORM room for optimizations. If you call the EntityManager and ask for an entity with a specific ID twice, it will return the same instance:
Only one SELECT query will be fired against the database here. In the second
call MikroORM will check the identity map first and will skip the database round trip as
it will find the entity already loaded.
The identity map being indexed by primary keys only allows shortcuts when you ask for objects by primary key. When you query by other properties, you will still get the same reference, but two separate database calls will be made:
MikroORM only knows objects by id, so a query for different criteria has to go to the database,
even if it was executed just before. But instead of creating a second
Author object MikroORM
first gets the primary key from the row and checks if it already has an object inside the
UnitOfWork with that primary key.
Persisting Managed Entities
The identity map has a second use-case. When you call
em.flush(), MikroORM will
ask the identity map for all objects that are currently managed. This means you don't have to
em.persistLater() over and over again to pass known objects to the
EntityManager. This is a NO-OP for known entities, but leads to much code written that is
confusing to other developers.
The following code WILL update your database with the changes made to the
even if you did not call
How MikroORM Detects Changes
MikroORM is a data-mapper that tries to achieve persistence-ignorance (PI). This means you map JS objects into a relational database that do not necessarily know about the database at all. A natural question would now be, "how does MikroORM even detect objects have changed?".
For this MikroORM keeps a second map inside the
UnitOfWork. Whenever you fetch an object
from the database MikroORM will keep a copy of all the properties and associations inside
Now whenever you call
em.flush() MikroORM will iterate over all entities you
previously marked for persisting via
em.persistLater(). For each object it will
compare the original property and association values with the values that are currently set
on the object. If changes are detected then the object is queued for a UPDATE operation.
Only the fields that actually changed are updated.
First and most important implication of having Unit of Work is that it allows handling transactions automatically.
When you call
em.flush(), all computed changes are queried inside a database
transaction (if supported by given driver). This means that you can control the boundaries
of transactions simply by calling
em.persistLater() and once all your changes
are ready, simply calling
flush() will run them inside a transaction.
You can also control the transaction boundaries manually via
You can find more information about transactions in Transactions and concurrency page.
Beware: Auto-flushing and Transactions
Since MikroORM v3, default value for
false. That means you need to call
em.flush()yourself to persist changes into database. You can still change this via ORM's options to ease the transition but generally it is not recommended.
Originally there was only
em.persist(entity, flush = true) method, that was
automatically flushing changes to database, if not given second
false parameter. This
behaviour can be now changed via
autoFlush option when initializing the ORM:
When using driver that supports transactions (all SQL drivers), you should either keep auto-flushing
disabled, or use
persistLater() method instead, as otherwise each
persist() call will immediately
create new transaction to run the query.
This part of documentation is highly inspired by doctrine internals docs as the behaviour here is pretty much the same.