<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Martin Adámek</title>
    <description>The latest articles on DEV Community by Martin Adámek (@b4nan).</description>
    <link>https://dev.to/b4nan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F162460%2F14911e2d-e9f2-484b-9cb0-a5ea9ad15f8d.jpeg</url>
      <title>DEV Community: Martin Adámek</title>
      <link>https://dev.to/b4nan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/b4nan"/>
    <language>en</language>
    <item>
      <title>MikroORM 6: Polished</title>
      <dc:creator>Martin Adámek</dc:creator>
      <pubDate>Mon, 08 Jan 2024 08:01:49 +0000</pubDate>
      <link>https://dev.to/b4nan/mikroorm-6-polished-3ac5</link>
      <guid>https://dev.to/b4nan/mikroorm-6-polished-3ac5</guid>
      <description>&lt;p&gt;After more than a year in the development, I am thrilled to announce the next major version of MikroORM has just become stable. It brings many improvements throughout the whole system, and doubles down on type-safety and strictness.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VWR9pU13--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/improving.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VWR9pU13--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/improving.jpg" alt="" width="600" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In case you don’t know…
&lt;/h3&gt;

&lt;p&gt;If you never heard of &lt;a href="https://github.com/mikro-orm/mikro-orm"&gt;MikroORM&lt;/a&gt;, it’s a TypeScript data-mapper ORM with Unit of Work and Identity Map. It supports MongoDB, MySQL, PostgreSQL, and SQLite drivers currently. Key features of the ORM are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#implicit-transactions"&gt;Implicit transactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#changeset-based-persistence"&gt;ChangeSet based persistence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/identity-map/"&gt;Identity map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EeIxLOIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/mikro-orm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EeIxLOIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/mikro-orm.png" alt="" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the full &lt;a href="https://medium.com/dailyjs/introducing-mikro-orm-typescript-data-mapper-orm-with-identity-map-9ba58d049e02"&gt;introductory article here&lt;/a&gt; (but note that many things have changed since that was written) or &lt;a href="https://mikro-orm.io/"&gt;browse through the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick summary of 5.x releases
&lt;/h3&gt;

&lt;p&gt;Before we dive into all the things v6, let’s mention some of the important additions from 5.x feature releases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;em.upsert()&lt;/code&gt; and &lt;code&gt;em.upsertMany()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;custom pivot table entity&lt;/li&gt;
&lt;li&gt;automatic relation discovery&lt;/li&gt;
&lt;li&gt;fulltext search support&lt;/li&gt;
&lt;li&gt;explicit serialization&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rel()&lt;/code&gt; and &lt;code&gt;ref()&lt;/code&gt; helpers&lt;/li&gt;
&lt;li&gt;new &lt;code&gt;Collection&lt;/code&gt; helpers (&lt;code&gt;map/filter/reduce/exists/find/indexBy/...&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But enough of the history lesson, let’s talk about the future!&lt;/p&gt;

&lt;h2&gt;
  
  
  Type safety
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g_rLg8_n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/typesafe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g_rLg8_n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/typesafe.jpg" alt="" width="600" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the biggest improvements in v6 is by far the overhauled typing. While v5 brought a base for this with strict &lt;code&gt;populate&lt;/code&gt; hint and the &lt;code&gt;Loaded&lt;/code&gt; type, v6 doubles down on it. Many of the internal types have been refactored to improve both strictness and autocomplete capabilities. So what actually changed?&lt;/p&gt;

&lt;h3&gt;
  
  
  Strict partial loading
&lt;/h3&gt;

&lt;p&gt;The most visible part is the partial loading, also known as the &lt;code&gt;fields&lt;/code&gt; option. Let's take a look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// article is typed to `Loaded&amp;lt;Article, never, 'title' | 'author.email'&amp;gt;`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;author.email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok, PK is selected automatically&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok, title is selected&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publisher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publisher&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// fail, not selected&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok, PK is selected automatically&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok, selected&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// fail, not selected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Loaded&lt;/code&gt; type now understands partial loading too, and this example will fail to compile because of accessing the author's name which is not loaded. Note that we also skipped the &lt;code&gt;populate&lt;/code&gt; hint from this example, as it is inferred from our partial loading hint.&lt;/p&gt;

&lt;p&gt;What if you wanted to exclude just a few columns instead of white-listing what you want to load? We got you covered, v6 adds a new &lt;code&gt;exclude&lt;/code&gt; option which does exactly that - and it is strictly typed as well!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// article is typed to `Loaded&amp;lt;User, never, never, 'email'&amp;gt;`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok, PK is selected automatically&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ok, selected&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// fail, excluded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the &lt;a href="https://stackblitz.com/edit/mikro-orm-v6-strict-partial-loading?file=basic.test.ts"&gt;live demo&lt;/a&gt; on StackBlitz.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Opt&lt;/code&gt; type
&lt;/h3&gt;

&lt;p&gt;While v5 introduced the strict typing for &lt;code&gt;em.create()&lt;/code&gt;, it was a bit cumbersome, as we now have to distinguish properties with a runtime default (so technically optional properties, but on type level they are seen as required). A new symbol called &lt;code&gt;OptionalProps&lt;/code&gt; was introduced to mark such defaults, so they are not required in the &lt;code&gt;em.create&lt;/code&gt; type. The symbol approach was mainly problematic when you wanted to define some properties like this in a custom base entity.&lt;/p&gt;

&lt;p&gt;In v6, you can leverage the new &lt;code&gt;Opt&lt;/code&gt; type, which is used on property level (as opposed to the entity level &lt;code&gt;OptionalProps&lt;/code&gt; symbol). This effectively removes the problems with extensions and added generics. You can use the type in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;with generics: &lt;code&gt;middleName: Opt&amp;lt;string&amp;gt; = '';&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;with intersections: &lt;code&gt;middleName: string &amp;amp; Opt = '';&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both will work the same, and can be combined with the &lt;code&gt;OptionalProps&lt;/code&gt; symbol approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Opt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PrimaryKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Property&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@mikro-orm/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-next-line&lt;/span&gt;
  &lt;span class="nx"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Opt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;Hidden&lt;/code&gt; type
&lt;/h3&gt;

&lt;p&gt;Similarly to the &lt;code&gt;Opt&lt;/code&gt; type used for marking optional properties, we have the &lt;code&gt;Hidden&lt;/code&gt; type (and &lt;code&gt;HiddenProps&lt;/code&gt; symbol) for marking properties that should be hidden when serializing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;hiddenField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Hidden&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;otherHiddenField&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those properties won't be accessible on the DTO:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bookDTO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;bookDTO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hiddenField&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// fails&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Populating all relations
&lt;/h3&gt;

&lt;p&gt;Previously, you were allowed to populate all relations via &lt;code&gt;populate: true&lt;/code&gt;, but it wasn't type-safe - the resulting &lt;code&gt;Loaded&lt;/code&gt; type was not respecting this option. In v6, you can use &lt;code&gt;populate: ['*']&lt;/code&gt; which will work with the &lt;code&gt;Loaded&lt;/code&gt; type correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;populate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;populate&lt;/code&gt; hint now also accepts &lt;code&gt;false&lt;/code&gt; as a way to disable eager loading of relations (those marked with &lt;code&gt;eager: true&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Populate based on filter
&lt;/h3&gt;

&lt;p&gt;When you filter by a nested relation value, the target table is automatically joined, but nothing is selected, the join is only used for the where condition. In v6, you can use &lt;code&gt;populate: ['$infer']&lt;/code&gt; to automatically populate such relations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this will populate all the books and their authors, all via a single query&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BookTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;populate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$infer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Primary key type inference
&lt;/h3&gt;

&lt;p&gt;If you use composite keys or non-standard primary key names, you probably know about &lt;code&gt;PrimaryKeyType&lt;/code&gt; and &lt;code&gt;PrimaryKeyProp&lt;/code&gt; symbols. While they worked fine, there was no need to have two of them—and people were often confused how they work, as one required a union type of primary property names, while the other was a tuple type. This is now consolidated into a single &lt;code&gt;PrimaryKeyProp&lt;/code&gt; symbol, which accepts a tuple with property names&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;@Entity()
&lt;span class="p"&gt;class Foo {
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  @ManyToOne(() =&amp;gt; Bar, { primary: true })
  bar!: Bar;
&lt;span class="err"&gt;
&lt;/span&gt;  @ManyToOne(() =&amp;gt; Baz, { primary: true })
  baz!: Baz;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;-  [PrimaryKeyType]?: [number, number];
-  [PrimaryKeyProp]?: 'bar' | 'baz';
&lt;/span&gt;&lt;span class="gi"&gt;+  [PrimaryKeyProp]?: ['bar', 'baz'];
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some methods and interfaces like &lt;code&gt;Ref&lt;/code&gt; allowed you to pass in the primary key property via second generic type argument, this is now also removed in favor of the automatic inference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplified &lt;code&gt;BaseEntity&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The optional ORM &lt;code&gt;BaseEntity&lt;/code&gt; used to have two generic parameters, one for the entity type and the other for the primary key type. They are both removed in v6. The former has been replaced with &lt;code&gt;this&lt;/code&gt; type, the latter with the &lt;code&gt;PrimaryKeyProp&lt;/code&gt; symbol.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-class User extends BaseEntity&amp;lt;User&amp;gt; { ... }
&lt;/span&gt;&lt;span class="gi"&gt;+class User extends BaseEntity { ... }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implicit serialization
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---P8K3Rc4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/godeeper.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---P8K3Rc4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/godeeper.jpg" alt="" width="600" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's talk about the changes in serialization. There are two ways to serialize your entities—implicit via &lt;code&gt;wrap(entity).toObject()&lt;/code&gt;, which is called automatically when you do &lt;code&gt;JSON.stringify(entity)&lt;/code&gt;, and explicit via &lt;code&gt;serialize()&lt;/code&gt; helper.&lt;/p&gt;

&lt;p&gt;Implicit serialization now works entirely based on &lt;code&gt;populate&lt;/code&gt; and &lt;code&gt;fields&lt;/code&gt; hints. This means that, unless you explicitly marked some entity as populated via &lt;code&gt;wrap(entity).populated()&lt;/code&gt;, it will be part of the serialized form only if it was part of the &lt;code&gt;populate&lt;/code&gt; hint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// let's say both Author and Book entity has a M:1 relation to Publisher entity&lt;/span&gt;
&lt;span class="c1"&gt;// we only populate the publisher relation of the Book entity&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;populate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;books.publisher&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publisher&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// only the FK, e.g. `123`&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;publisher&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// populated, e.g. `{ id: 123, name: '...' }`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, the implicit serialization now respects the partial loading hints too. Previously, all loaded properties were serialized, and partial loading worked only on the database query level. Since v6, we also prune the data on runtime. This means that unless the property is part of the partial loading hint (&lt;code&gt;fields&lt;/code&gt; option), it won't be part of the DTO - only exception is the primary key, you can optionally hide it via &lt;code&gt;hidden: true&lt;/code&gt; in the property options. The main difference here will be the foreign keys, those are often automatically selected as they are needed to build the entity graph, but will no longer be part of the DTO.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneOrFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;books.publisher.name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// only the publisher's name will be available, previously there would be also `book.author`&lt;/span&gt;
&lt;span class="c1"&gt;// `{ id: 1, books: [{ id: 2, publisher: { id: 3, name: '...' } }] }`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also works for embeddables, including nesting and object mode. And speaking of embeddables—they now also support the &lt;code&gt;fieldName&lt;/code&gt; option, again, including the nesting and object mode, effectively allowing partial loading on the object embeddables (so JSON properties) too.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;forceObject&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When you serialize an entity with unpopulated relation, it will result in a foreign key value, e.g. &lt;code&gt;book.author&lt;/code&gt; will be number if you don't populate the &lt;code&gt;author&lt;/code&gt; relation. In v6, you can use the &lt;code&gt;forceObject&lt;/code&gt; serialization option to get an object there instead, e.g. &lt;code&gt;book.author&lt;/code&gt; will be &lt;code&gt;{ id: 1 }&lt;/code&gt; instead of just &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To have the DTO properly typed, you can use the &lt;code&gt;Config&lt;/code&gt; symbol, preferably in your own base entity, as this flag will affect all your entities globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DefineConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PrimaryKey&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@mikro-orm/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// highlight-next-line&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;]?:&lt;/span&gt; &lt;span class="nx"&gt;DefineConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;forceObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;DefineConfig&lt;/code&gt; type will offer intellisense to the type config options. Right now, it only accepts a single property, but there might be more options like this going forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Joined strategy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0BYNbAHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/join.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0BYNbAHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/join.jpg" alt="" width="614" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The joined loading strategy was around for a while, but it had several implementation problems resulting in different behavior when compared to the default select-in strategy. But that actually changes now, the joined strategy is back on track and should be completely aligned with the select-in behavior.&lt;/p&gt;

&lt;p&gt;So what actually changed? The most important part is the support for &lt;code&gt;populateWhere: 'all'&lt;/code&gt;, which is the default behavior, and means "populate the full relations regardless of the where condition". This was previously not working with the joined strategy, as it was reusing the same join clauses as the where clause. In v6, the joined strategy will use a separate join branch for the populated relations.&lt;/p&gt;

&lt;p&gt;Since the strategies now behave the same, this finally unlocked the switch of the defaults for all the SQL drivers—the joined strategy is the new default. The joined strategy should usually be faster unless you join a lot of to-many relations (which would result in huge cartesian products).&lt;/p&gt;

&lt;h2&gt;
  
  
  Filters on relations
&lt;/h2&gt;

&lt;p&gt;Filters are now also applied to the relations, as part of &lt;code&gt;JOIN ON&lt;/code&gt; condition. If a filter exists on a M:1 or 1:1 relation target, such an entity will be automatically joined, and when the foreign key is defined as &lt;code&gt;NOT NULL&lt;/code&gt;, it will result in an &lt;code&gt;INNER JOIN&lt;/code&gt; rather than &lt;code&gt;LEFT JOIN&lt;/code&gt;. This is especially important for implementing soft deletes via filters, as the foreign key might point to a soft-deleted entity. When this happens, the automatic &lt;code&gt;INNER JOIN&lt;/code&gt; will result in such a record not being returned at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cursor-based pagination
&lt;/h2&gt;

&lt;p&gt;As an alternative to the offset-based pagination with &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;offset&lt;/code&gt;, you can now &lt;a href="https://mikro-orm.io/docs/entity-manager#cursor-based-pagination"&gt;paginate based on a cursor&lt;/a&gt;. A cursor is an opaque string that defines a specific place in ordered entity graph. You can use &lt;code&gt;em.findByCursor()&lt;/code&gt; to access those options. Under the hood, it will call &lt;code&gt;em.find()&lt;/code&gt; and &lt;code&gt;em.count()&lt;/code&gt; just like the &lt;code&gt;em.findAndCount()&lt;/code&gt; method, but will use the cursor options instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentCursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;previousCursor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// cursor instance&lt;/span&gt;
  &lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// to fetch next page&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextCursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentCursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endCursor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// opaque string&lt;/span&gt;
  &lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// to fetch next page&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextCursor2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lastSeenId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// entity-like POJO&lt;/span&gt;
  &lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Cursor&lt;/code&gt; object provides the following interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Cursor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;totalCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;startCursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WzRd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;endCursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WzZd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;hasPrevPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Raw SQL fragments
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sg2mHG3X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/let-the-raw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sg2mHG3X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/let-the-raw.jpg" alt="" width="600" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The raw SQL fragments used to be detected automatically, which wasn't very precise. In v6, a new &lt;code&gt;raw&lt;/code&gt; static helper is introduced to deal with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lower(email)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo@bar.baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helper now replaces the removed &lt;code&gt;expr()&lt;/code&gt; function, which was only an escape hatch for strictly typed &lt;code&gt;FilterQuery&lt;/code&gt;, but wasn't required on runtime. It offers similar API, e.g. you can pass in a callback and get the current alias (based on the scope of execution) for given column:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`lower(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.title)`&lt;/span&gt;&lt;span class="p"&gt;)]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Unlike in v5, this is now required way to mark your raw SQL fragments. Without it, you'd end up with the fragment being quoted as a regular string value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The raw query can be also parametric, you can use &lt;code&gt;?&lt;/code&gt; for values and &lt;code&gt;??&lt;/code&gt; for keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// this will result in properly quoted sql, e.g. `lower("email")`&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lower(??)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo@bar.baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And while the &lt;code&gt;raw&lt;/code&gt; helper is the most universal one you can use, there is also a new &lt;code&gt;sql&lt;/code&gt; tagged template function, which resolves to it too, if you prefer that kind of interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`lower(email)`&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo@bar.baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fragments can be also used in your entity definition, to set raw database defaults. This is basically a shortcut for &lt;code&gt;prop.defaultRaw&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`now()`&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;createdAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there is more to this, the &lt;code&gt;sql&lt;/code&gt; function also offers several helper functions you can use, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sql.ref()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sql.now()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sql.lower()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sql.upper()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about this in &lt;a href="https://mikro-orm.io/docs/raw-queries"&gt;Using raw SQL query fragments&lt;/a&gt; section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subquery operators &lt;code&gt;$some&lt;/code&gt;, &lt;code&gt;$none&lt;/code&gt; and &lt;code&gt;$every&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In addition to the regular operators that translate to a real SQL operator expression (e.g. &lt;code&gt;&amp;gt;=&lt;/code&gt;), you can also use the following collection operators:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;operator&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$some&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finds collections that have some record matching the condition.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finds collections that have no records matching the condition.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$every&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finds collections where every record is matching the condition.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This will be resolved as a subquery condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// finds all authors that have some book called `Foo`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$some&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// finds all authors that have no books called `Foo`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$none&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// finds all authors that have every book called `Foo`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$every&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The condition object can be also empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// finds all authors that have at least one book&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$some&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// finds all authors that have no books&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$none&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Subquery joining
&lt;/h2&gt;

&lt;p&gt;Subqueries are now better supported all over the place. Namely, you can join a subquery, as well as use a subquery in &lt;code&gt;qb.from()&lt;/code&gt; method. One use case where this is handy is when you want to limit a joined relation, e.g. you have a 1:M collection, and you are interested only in the first item. In the following example, we join on the &lt;code&gt;Author.books&lt;/code&gt; collection, overriding the implicit join branch with a custom subquery that has a &lt;code&gt;limit 1&lt;/code&gt; on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// subquery can be a knex query builder as well&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subquery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createQueryBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;asc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createQueryBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// pass in both the property path and the subquery into the first argument as a tuple&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;leftJoinAndSelect&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a.books&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subquery&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// you can join more relations on top of the subquery join&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;leftJoinAndSelect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b.tags&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getResultList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dataloader support for references and collections
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v75eqjXt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/dataloader.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v75eqjXt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/dataloader.jpg" alt="" width="540" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MikroORM now provide out-of-box support for loading &lt;code&gt;Reference&lt;/code&gt; and &lt;code&gt;Collection&lt;/code&gt; properties via dataloader. This feature needs to be enabled either globally (via ORM config) or locally (via &lt;code&gt;FindOptions&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;MikroORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dataloader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can use &lt;code&gt;Promise.all&lt;/code&gt; on such objects, and it will automatically resolve to a batched select query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="c1"&gt;// or when the dataloader support is not enabled globally:&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;dataloader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially useful with GraphQL since it automatically solves its notorious N+1 problem, without you even noticing it: you won't even need &lt;code&gt;Promise.all&lt;/code&gt; since all the requests will occur within a single tick of the event loop and will be coalesced by the dataloader library.&lt;/p&gt;

&lt;p&gt;More about this in the new &lt;a href="https://mikro-orm.io/docs/dataloaders"&gt;dataloader section&lt;/a&gt;. You can also check out &lt;a href="https://github.com/darkbasic/mikro-orm-accounts-example"&gt;this example repository&lt;/a&gt; which leverages the dataloader (as well as Accounts.js library).&lt;/p&gt;

&lt;p&gt;Shout out to &lt;strong&gt;&lt;a href="https://github.com/darkbasic"&gt;Niccolò Belli&lt;/a&gt;&lt;/strong&gt;, who contributed this feature and is working on a &lt;a href="https://github.com/darkbasic/mikro-orm-dataloaders"&gt;more advanced version&lt;/a&gt; which supports dataloader also for &lt;code&gt;em.find()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging improvements
&lt;/h2&gt;

&lt;p&gt;Logging support has been greatly improved. You can now set up a custom logger context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;loggerContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meaningOfLife&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomLogger&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;DefaultLogger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoggerNamespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;LogContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;meaningOfLife&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// 42&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This context can be specific to the &lt;code&gt;EntityManager&lt;/code&gt; fork, and will get the &lt;code&gt;EntityManager&lt;/code&gt; ID automatically, so you can now track which request context/fork fired what queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fork&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;loggerContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meaningOfLife&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="c1"&gt;// the logger context here will be { id: 3, meaningOfLife: 42 } &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logger also supports query labels (simple way to alter what gets printed), index hints and query comments, and more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Author Retrieval - /authors/me&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// [query] (Author Retrieval - /authors/me) select "a0".* from "author" as "a0" where "a0"."id" = 1 limit 1 [took 2 ms]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The label can be also set via &lt;code&gt;loggerContext&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Logging can be now selectively enabled/disabled via &lt;code&gt;FindOptions&lt;/code&gt;. this works in both ways, if you globally disable logging, you can selectively enable it via &lt;code&gt;FindOptions&lt;/code&gt;, as well as the other way around.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// MikroORM.init({ debug: true });&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Overrides config and displays no logger output&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="c1"&gt;// MikroORM.init({ debug: false });&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Overrides config and displays logger output&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="c1"&gt;// MikroORM.init({ debug: ['query-labels'] });&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;debugMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Overrides config and displays logger output for query&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more about the logger improvements in the &lt;a href="https://mikro-orm.io/docs/logging"&gt;logging section&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improved change-tracking of M:N relations
&lt;/h2&gt;

&lt;p&gt;M:N relations were always a bit problematic, the way they were implemented was only checking the owning side for changes. Thanks to the propagation of changes, it allowed working with the inverse side too, as long as the items you added/removed from the collection were loaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BookTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// tag.books in an inverse side, this used to fail, but now it works!&lt;/span&gt;
&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This restriction is no longer valid, and changes made to inverse sides of M:N collections are also tracked. Moreover, all queries that are altering pivot tables are now properly batched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending &lt;code&gt;EntityManager&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DQPs0OvZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/extension.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DQPs0OvZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/extension.jpg" alt="" width="600" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is now possible to extend the &lt;code&gt;EntityManager&lt;/code&gt; with your own custom methods. The type is inferred automatically from the config if possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MikroORM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EntityManager&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@mikro-orm/sqlite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyEntityManager&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;EntityManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;myCustomMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;MikroORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
  &lt;span class="na"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:memory:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// highlight-next-line&lt;/span&gt;
  &lt;span class="na"&gt;entityManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyEntityManager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;MyEntityManager&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myCustomMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;GeneratedCacheAdapter&lt;/code&gt; for production usage
&lt;/h2&gt;

&lt;p&gt;One of the ways you can define your entity metadata is leveraging the TypeScript compiler API via &lt;code&gt;ts-morph&lt;/code&gt;, which allows extracting the type information that would be otherwise lost on compilation (and is not available via &lt;code&gt;reflect-metadata&lt;/code&gt;). While this approach works nice locally, it had several hard problems around it, the most obvious one is the dependency on TypeScript, which you don't want to have in your production builds.&lt;/p&gt;

&lt;p&gt;In v6, MikroORM lets you generate a production cache bundle into a single JSON file via CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx mikro-orm cache:generate &lt;span class="nt"&gt;--combined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create &lt;code&gt;./temp/metadata.json&lt;/code&gt; file which can be used together with &lt;code&gt;GeneratedCacheAdapter&lt;/code&gt; in your production configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GeneratedCacheAdapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MikroORM&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@mikro-orm/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;MikroORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;metadataCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GeneratedCacheAdapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./temp/metadata.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way you can keep the &lt;code&gt;@mikro-orm/reflection&lt;/code&gt; package as a development dependency only, use the CLI to create the cache bundle, and depend only on that in your production build.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The cache bundle can be statically imported, which is handy in case you are using some bundler.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Entity Generator improvements
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mikro-orm.io/docs/entity-generator"&gt;EntityGenerator&lt;/a&gt; now automatically detects more M:N relations—including those with an autoincrement primary key (so fixed order), or even unrelated additional columns. Over time, we might get closer to a proper schema-first approach.&lt;/p&gt;

&lt;p&gt;Shout out to &lt;strong&gt;&lt;a href="https://github.com/boenrobot"&gt;Vasil Rangelov&lt;/a&gt;&lt;/strong&gt;, who contributed this feature and is working on more improvements in the EntityGenerator, e.g. ability to override the generated entities' metadata.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inference of default values
&lt;/h2&gt;

&lt;p&gt;When defining properties with a runtime default value, the &lt;code&gt;reflect-metadata&lt;/code&gt; provider fails to infer the type property. This is no longer a problem in v6, as the discovery mechanism now automatically tries to &lt;a href="https://mikro-orm.io/docs/defining-entities"&gt;infer the type from the runtime defaults&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;@Property()
&lt;span class="gd"&gt;-created: Data = new Date();
&lt;/span&gt;&lt;span class="gi"&gt;+created = new Date();
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that this works only if your entity can be constructed without any constructor parameters. It is fine to have them, but the constructor cannot fail if they are not provided for this auto-detection to work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Other notable changes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Virtual entities now allow M:1 and 1:1 relations.&lt;/li&gt;
&lt;li&gt;New &lt;a href="https://mikro-orm.io/docs/quick-start#synchronous-initialization"&gt;&lt;code&gt;MikroORM.initSync()&lt;/code&gt; method&lt;/a&gt; allows initializing the ORM synchronously.&lt;/li&gt;
&lt;li&gt;Propagation and change-tracking works with &lt;code&gt;useDefineForClassFields&lt;/code&gt; enabled.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/mikro-orm/mikro-orm/pull/3814"&gt;Removed static &lt;code&gt;require&lt;/code&gt; calls&lt;/a&gt; that were problematic when bundling.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/repositories#removed-methods-from-entityrepository-interface"&gt;Removed &lt;code&gt;persist/remove/flush&lt;/code&gt; from repository interface.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/upgrading-v5-to-v6#the-type-option-is-removed-in-favour-of-driver-exports"&gt;The &lt;code&gt;type&lt;/code&gt; option is removed in favor of driver exports and &lt;code&gt;defineConfig&lt;/code&gt;.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/configuration#extensions"&gt;ORM extensions&lt;/a&gt;—a way to tell the ORM about optional dependencies like Seeder or Migrator without the need to declare peer dependencies.&lt;/li&gt;
&lt;li&gt;All drivers now re-export the &lt;code&gt;@mikro-orm/core&lt;/code&gt; package, so you no longer have to think about which package to import from - just use the driver package.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/using-bigint-pks"&gt;Native BigInt support&lt;/a&gt;, allowing to set the mapping to either &lt;code&gt;bigint&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt; or &lt;code&gt;string&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/upgrading-v5-to-v6#embedded-properties-respect-namingstrategy"&gt;Embedded properties respect &lt;code&gt;NamingStrategy&lt;/code&gt;, including object embeddables.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Entities are added to the identity map on &lt;code&gt;em.persist()&lt;/code&gt; if they have a primary key.&lt;/li&gt;
&lt;li&gt;Native support for &lt;a href="https://mikro-orm.io/docs/defining-entities#sql-generated-columns"&gt;generated columns&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Support for lateral sub-query joins.&lt;/li&gt;
&lt;li&gt;Support for &lt;a href="https://mikro-orm.io/docs/defining-entities#postgresql-native-enums"&gt;native enums in postgres&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Support &lt;a href="https://mikro-orm.io/docs/guide/05-type-safety#scalarreference-wrapper"&gt;&lt;code&gt;Ref&lt;/code&gt; wrapper on scalar properties&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/configuration#onmetadata-hook"&gt;Discovery hooks &lt;code&gt;onMetadata&lt;/code&gt; and &lt;code&gt;afterDiscovered&lt;/code&gt;&lt;/a&gt; allowing to modify the metadata in any way you want.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And &lt;em&gt;many many&lt;/em&gt; more, see the &lt;a href="https://github.com/mikro-orm/mikro-orm/blob/master/CHANGELOG.md#600-2024-01-08"&gt;full changelog here&lt;/a&gt;. Also be sure to check the &lt;a href="https://mikro-orm.io/docs/upgrading-v5-to-v6"&gt;upgrading guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  One more thing…
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1GJFweBg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/one-more-thing-jobs.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1GJFweBg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mikro-orm.io/img/blog/one-more-thing-jobs.webp" alt="" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over time, while some people liked the current documentation, there were also people disliking it. It wasn't really beginner-friendly, as it only described the distinct features, but was lacking some tutorials describing how to set things up as a whole.&lt;/p&gt;

&lt;p&gt;A lot of the documentation for v6 has been updated and polished, and a completely new &lt;strong&gt;&lt;a href="https://mikro-orm.io/docs/guide"&gt;Getting Started Guide&lt;/a&gt;&lt;/strong&gt; was added, accompanied by an &lt;a href="https://github.com/mikro-orm/guide"&gt;example repository&lt;/a&gt;. It describes how to build and test an API from scratch with MikroORM, Fastify, ESM, Vitest, JWT, and some other tools. Unlike the rest of the docs, you can read it from top to bottom as a tutorial. I will continue extending the guide over time, especially the final section about type safety.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Like&lt;/em&gt; &lt;a href="https://mikro-orm.io/"&gt;&lt;em&gt;MikroORM&lt;/em&gt;&lt;/a&gt;&lt;em&gt;? ⭐️&lt;/em&gt; &lt;a href="https://github.com/mikro-orm/mikro-orm"&gt;&lt;em&gt;Star it&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on GitHub and share this article with your friends. If you want to support the project financially, you can do so via&lt;/em&gt; &lt;a href="https://github.com/sponsors/B4nan"&gt;&lt;em&gt;GitHub Sponsors&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>typescript</category>
      <category>sql</category>
      <category>orm</category>
      <category>database</category>
    </item>
    <item>
      <title>MikroORM 5: Stricter, Safer, Smarter</title>
      <dc:creator>Martin Adámek</dc:creator>
      <pubDate>Sun, 06 Feb 2022 18:59:29 +0000</pubDate>
      <link>https://dev.to/b4nan/mikroorm-5-stricter-safer-smarter-l4g</link>
      <guid>https://dev.to/b4nan/mikroorm-5-stricter-safer-smarter-l4g</guid>
      <description>&lt;p&gt;The next major version of MikroORM has been just released. The title says: Stricter, Safer, Smarter — why?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F430%2F0%2AatMJ3hrlUosSpnQy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F430%2F0%2AatMJ3hrlUosSpnQy.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Greatly improved type safety (e.g. populate and partial loading hints)&lt;/li&gt;
&lt;li&gt;Auto-flush mode (so we never lose in-memory changes)&lt;/li&gt;
&lt;li&gt;Automatic refreshing of loaded entities (say goodby to refresh: true)&lt;/li&gt;
&lt;li&gt;Reworked schema diffing with automatic down migrations support&lt;/li&gt;
&lt;li&gt;and &lt;a href="https://github.com/mikro-orm/mikro-orm/blob/master/CHANGELOG.md#500-rc0-2022-01-23" rel="noopener noreferrer"&gt;many many more&lt;/a&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This time it took almost a year to get here — initial work on v5 started &lt;a href="https://github.com/mikro-orm/mikro-orm/issues/1623" rel="noopener noreferrer"&gt;back in March 2021&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  In case you don’t know…
&lt;/h3&gt;

&lt;p&gt;If you never heard of &lt;a href="https://github.com/mikro-orm/mikro-orm" rel="noopener noreferrer"&gt;MikroORM&lt;/a&gt;, it’s a TypeScript data-mapper ORM with Unit of Work and Identity Map. It supports MongoDB, MySQL, PostgreSQL, and SQLite drivers currently. Key features of the ORM are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#implicit-transactions" rel="noopener noreferrer"&gt;Implicit transactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#changeset-based-persistence" rel="noopener noreferrer"&gt;ChangeSet based persistence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/identity-map/" rel="noopener noreferrer"&gt;Identity map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AfKozvvTJns0y3w5U.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AfKozvvTJns0y3w5U.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the full &lt;a href="https://medium.com/dailyjs/introducing-mikro-orm-typescript-data-mapper-orm-with-identity-map-9ba58d049e02" rel="noopener noreferrer"&gt;introductory article here&lt;/a&gt; (but note that many things have changed since that was written) or &lt;a href="https://mikro-orm.io/" rel="noopener noreferrer"&gt;browse through the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick summary of 4.x releases
&lt;/h3&gt;

&lt;p&gt;Before we dive into all the things v5, let’s recap what happened in 4.x releases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/caching/" rel="noopener noreferrer"&gt;Result cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm/pull/959" rel="noopener noreferrer"&gt;Automatic transaction context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/embeddables/#nested-embeddables" rel="noopener noreferrer"&gt;Nested embeddables&lt;/a&gt; and many other improvements in this domain&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/configuration/#using-environment-variables" rel="noopener noreferrer"&gt;Using env vars for configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But enough of the history lesson, let’s talk about the future!&lt;/p&gt;

&lt;h3&gt;
  
  
  Improved type safety
&lt;/h3&gt;

&lt;p&gt;Let’s jump right into the most interesting feature — strict typing (almost) everywhere! em.create(), toJSON(), toObject(), populate, partial loading, and order by hints, all of that (and even more!) is now strictly typed.&lt;/p&gt;

&lt;p&gt;Let’s check the following example:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;First, we use em.create() to build the whole entity graph in a single step. It will validate the payload for both types and optionality. Some properties on the entity might have default values provided via hooks or database functions — while we might want to define them as required properties, they should act as optional in the context of em.create(). To deal with this problem, we can specify such properties that should be considered as optional via OptionalProps symbol:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Some property names are always considered as optional: id, _id, uuid.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then we load all Author entities, populating their books and the book tags. All of the FindOptions here are strictly typed, moreover, we could even skip the populate hint as it can be inferred from fields option automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F0%2A3g12H4O5KrzmQMrk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F0%2A3g12H4O5KrzmQMrk.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We might still need some type casting for DTOs. The serialized form of an entity can be very unpredictable — there are many variables that define how an entity will be serialized, e.g. loaded relation vs reference, property serializers, lazy properties, custom entity serializer/toJSON method, eager loading, recursion checks, … Therefore, all relations on the EntityDTO type are considered as loaded, this is mainly done to allow better DX as if we had all relations typed as Primary | EntityDTO (e.g. number | EntityDTO), it would be impossible to benefit from intellisense/autosuggestions. Imagine this scenario:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Validation improvements
&lt;/h3&gt;

&lt;p&gt;Adding on top of the compile-time validation, we also get a runtime validation right before insert queries are fired, to ensure required properties have their values. This is important mainly in mongo, where we don’t have optionality checks on the schema level.&lt;/p&gt;

&lt;p&gt;When we try to use the CLI without installing it locally, we also get a warning. And what if we forget to update some of the ORM packages and ended up with version mismatch and multiple installed core packages? We now validate that too!&lt;/p&gt;

&lt;h3&gt;
  
  
  Reworked schema diffing
&lt;/h3&gt;

&lt;p&gt;Schema diffing has been one of the weakest spots. Often, additional queries were produced or it was even impossible to get to a fully synchronized state.&lt;/p&gt;

&lt;p&gt;Schema diffing has been completely reworked to address all currently known issues, and adding &lt;em&gt;a bit more&lt;/em&gt; on top of that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Diffing foreign key constraints&lt;/li&gt;
&lt;li&gt;Proper index diffing (before we compared just names)&lt;/li&gt;
&lt;li&gt;Custom index expressions&lt;/li&gt;
&lt;li&gt;Comment diffing&lt;/li&gt;
&lt;li&gt;Column length diffing (e.g. numeric(10,2) or varchar(100))&lt;/li&gt;
&lt;li&gt;Changing primary key types&lt;/li&gt;
&lt;li&gt;Schema/namespace diffing (Postgres only)&lt;/li&gt;
&lt;li&gt;Automatic down migrations (no SQLite support yet)&lt;/li&gt;
&lt;li&gt;Check constraints support (Postgres only)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Smarter migrations
&lt;/h3&gt;

&lt;p&gt;In the production environment, we might want to use compiled migration files. Since v5, this should work almost out of the box, all we need to do is to configure the migrations path accordingly. Executed migrations now ignore the file extension, so we can use both node and ts-node on the same database. This is done in a backward-compatible manner.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Creating new migration will now automatically save the target schema snapshot into the migrations folder. This snapshot will be then used if we try creating a new migration, instead of using the current database schema. This means that if we try to create new migration before we run the pending ones, we still get the right schema diff (and no migration will be created if no additional changes were made).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Snapshots should be versioned just like the regular migration files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Auto-flush mode
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AJ74FKP7MaZoHO3Al.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AJ74FKP7MaZoHO3Al.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Up until now, flushing was always an explicit action. With v5, we can configure the flushing strategy, similarly to how JPA/hibernate work. We have 3 flush modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FlushMode.COMMIT - The EntityManager tries to delay the flush until the current transaction is committed, although it might flush prematurely too.&lt;/li&gt;
&lt;li&gt;FlushMode.AUTO - This is the default mode, and it flushes the EntityManager only if necessary.&lt;/li&gt;
&lt;li&gt;FlushMode.ALWAYS - Flushes the EntityManager before every query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FlushMode.AUTO will try to detect changes on the entity we are querying, and flush if there is an overlap:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;More about flush modes &lt;a href="https://mikro-orm.io/docs/unit-of-work/#flush-modes" rel="noopener noreferrer"&gt;in the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic refreshing of loaded entities
&lt;/h3&gt;

&lt;p&gt;Previously, when an entity was loaded and we needed to reload it, providing explicit refresh: true in the options was required. Refreshing of entity also had one problematic side effect — the entity data (used for computing changesets) were always updated based on the newly loaded entity, hence forgetting the previous state (resulting in possibly lost updates done on the entity before refreshing).&lt;/p&gt;

&lt;p&gt;Now we always merge the newly loaded data with the current state, and when we see an updated property, we keep the changed value instead. Moreover, for em.findOne() with a primary key condition, we try to detect whether it makes sense to reload an entity, by comparing the options and already loaded property names. In this step the fields and populate options are taken into account to support both partial loading and lazy properties.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For complex conditions in em.findOne() and for any queries via em.find(), we always do the query anyway, but now instead of ignoring the data in case such entity was loaded, we merge them in the same manner.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Seeder package
&lt;/h3&gt;

&lt;p&gt;MikroORM v5 now has a new package for seeding your database with initial or testing data. It allows creating entities via the same EntityManager API as usual, adding support for entity factories, and generating fake data via faker (the newly release community version).&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://mikro-orm.io/docs/seeding" rel="noopener noreferrer"&gt;seeder docs&lt;/a&gt; for more examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Polymorphic embeddables
&lt;/h3&gt;

&lt;p&gt;Polymorphic embeddables allow us to define multiple classes for a single embedded property and the right one will be used based on the discriminator column, similar to how single table inheritance works. While this currently works only for embeddables, support for polymorphic entities will be probably added in one of the 5.x releases.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Check out the &lt;a href="https://mikro-orm.io/docs/embeddables/#polymorphic-embeddables" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for a complete example.&lt;/p&gt;

&lt;p&gt;There are many other small improvements in embeddables, as well as many issues were addressed. Two examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for many-to-one relations (storing only primary key and being able to populate the relation same as with regular entities)&lt;/li&gt;
&lt;li&gt;Support for onCreate and onUpdate property options&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Populating lazy scalar properties
&lt;/h3&gt;

&lt;p&gt;Previously, the only way to populate a lazy scalar property was during the initial load of containing entity. If such entity was already loaded in the identity map (without this property), we needed to refresh its state — and potentially lose some state. MikroORM v5 allows to populate such properties via em.populate() too. Doing so will never override any in-memory changes we might have done on the entity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating references without EntityManager
&lt;/h3&gt;

&lt;p&gt;When we wanted to create a reference, so an entity that is represented only by its primary key, we always had to have access to the current EntityManager instance, as such entity always needed to be managed.&lt;/p&gt;

&lt;p&gt;Thanks to the new helper methods on the Reference class, we can now create entity references without access to EntityManager. This can be handy if you want to create a reference from an inside entity constructor:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;The Reference wrapper is an optional class to allow more type safety over relationships. Alternatively, we can use Reference.createNakedFromPK().&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This will create an unmanaged reference, that will be then merged to the EntityManager once owning entity gets flushed. Note that before we flush it, methods like Reference.init() or Reference.load() won’t be available as they require the EntityManager instance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smarter expr helper
&lt;/h3&gt;

&lt;p&gt;The expr() helper can be used to get around strict typing. It was an identity function, doing nothing more than returning its parameter — all it did was to tell TypeScript the value is actually of a different type (a generic string to be precise).&lt;/p&gt;

&lt;p&gt;We can now use the helper in two more ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With a callback signature to allow dynamic aliasing of the expression&lt;/li&gt;
&lt;li&gt;With an array argument to allow comparing tuples&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Awaitable QueryBuilder
&lt;/h3&gt;

&lt;p&gt;QueryBuilder is now aware of its type, and the getResult() and execute() methods are typed based on it. We can also await the QueryBuilder instance directly, which will automatically execute the QB and return the appropriate response. The QB instance is now typed based on usage of select/insert/update/delete/truncate methods to one of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SelectQueryBuilder — awaiting yields array of entities&lt;/li&gt;
&lt;li&gt;CountQueryBuilder — awaiting yields number&lt;/li&gt;
&lt;li&gt;InsertQueryBuilder — awaiting yields QueryResult&lt;/li&gt;
&lt;li&gt;UpdateQueryBuilder — awaiting yields QueryResult&lt;/li&gt;
&lt;li&gt;DeleteQueryBuilder — awaiting yields QueryResult&lt;/li&gt;
&lt;li&gt;TruncateQueryBuilder — awaiting yields QueryResult&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F798%2F0%2AjFsyXtSw1ZzZ9-cD.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F798%2F0%2AjFsyXtSw1ZzZ9-cD.jpg"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Wildcard schema entities
&lt;/h3&gt;

&lt;p&gt;Up until now, we were able to define entities in a specific schema, or without a schema. Such entities then used the schema based on ORM config or FindOptions. This allowed us to read entities from a specific schema, but we were missing the power of Unit of Work here.&lt;/p&gt;

&lt;p&gt;With v5, entity instances now hold schema name (as part of WrappedEntity). Managed entities will have the schema from FindOptions or metadata. Methods that create new entity instances like em.create() or em.getReference() now have an options parameter to allow setting the schema. We can also use wrap(entity).getSchema() and wrap(entity).setSchema().&lt;/p&gt;

&lt;p&gt;Entities can now specify wildcard schema via @Entity({ schema: '*' }). That way they will be ignored in SchemaGenerator unless the schema option is specified.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If we specify schema, the entity only exists in that schema&lt;/li&gt;
&lt;li&gt;If we define * schema, the entity can exist in any schema, always controlled by the parameter&lt;/li&gt;
&lt;li&gt;If we skip schema option, the value will be taken from global ORM config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More about this topic can be found &lt;a href="https://mikro-orm.io/docs/next/multiple-schemas#wildcard-schema" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deep assigning of entities
&lt;/h3&gt;

&lt;p&gt;Another weak spot was assigning new values to existing entities. While wrap().assign() was originally designed to update a single entity and its values, a lot of users wanted to assign an entity graph, updating relations in a single step too.&lt;/p&gt;

&lt;p&gt;With v5, the way how EntityAssigner detects what entity should be updated has changed. Assigning a deep entity graph should be possible by default, without any additional options. It works based on matching entity primary keys, so if you want to issue an update for a relationship instead of creating new relation, make sure you first load it and pass down its primary key to the assign helper:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;If we want to always update the entity, even without the entity PK being present in data, we can use updateByPrimaryKey: false:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;More examples on this topic can be found &lt;a href="https://mikro-orm.io/docs/entity-helper/#updating-deep-entity-graph" rel="noopener noreferrer"&gt;in the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experimental support for ES modules
&lt;/h3&gt;

&lt;p&gt;While MikroORM v5 is still compiled and published as CommonJS, we added several improvements that should allow using it with ESM projects too. Namely, we use the gen-esm-wrapper package to allow using named imports, and we use one nasty trick to keep dynamic imports instead of compiling them to require statements — for that we need to use MIKRO_ORM_DYNAMIC_IMPORTS env var. This should allow us to use folder-based discovery with ES modules, which was previously not possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other notable changes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Partial loading support (fields) for joined loading strategy&lt;/li&gt;
&lt;li&gt;AsyncLocalStorage used by default in the RequestContext helper&lt;/li&gt;
&lt;li&gt;onLoad event (like onInit, but allows async and fires only for loaded entities, not references)&lt;/li&gt;
&lt;li&gt;Exporting async functions from CLI config&lt;/li&gt;
&lt;li&gt;Configurable aliasing strategy for SQL&lt;/li&gt;
&lt;li&gt;Allow providing &lt;a href="https://mikro-orm.io/docs/logging" rel="noopener noreferrer"&gt;custom&lt;/a&gt;&lt;a href="https://mikro-orm.io/docs/logging" rel="noopener noreferrer"&gt;Logger instance&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/configuration/#persist-created-entities-automatically" rel="noopener noreferrer"&gt;persist option in&lt;/a&gt;&lt;a href="https://mikro-orm.io/docs/configuration/#persist-created-entities-automatically" rel="noopener noreferrer"&gt;em.create() and&lt;/a&gt;&lt;a href="https://mikro-orm.io/docs/configuration/#persist-created-entities-automatically" rel="noopener noreferrer"&gt;persistOnCreate global configuration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;M:N support in entity generator&lt;/li&gt;
&lt;li&gt;Support for specifying transaction isolation level&lt;/li&gt;
&lt;li&gt;Controlling &lt;a href="https://mikro-orm.io/docs/loading-strategies#population-where-condition" rel="noopener noreferrer"&gt;where condition for populate hints&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Revamped &lt;a href="https://mikro-orm.io/api" rel="noopener noreferrer"&gt;API docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;and &lt;em&gt;many many&lt;/em&gt; more, see the &lt;a href="https://github.com/mikro-orm/mikro-orm/blob/master/CHANGELOG.md#500-rc2-2022-02-03" rel="noopener noreferrer"&gt;full changelog here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also be sure to check the &lt;a href="https://mikro-orm.io/docs/upgrading-v4-to-v5" rel="noopener noreferrer"&gt;upgrading guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s next?
&lt;/h3&gt;

&lt;p&gt;Here is a list of things I would like to focus on going forward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allow specifying pivot entity for M:N relations (so we can have additional columns there, but still map it as M:N for reading purposes)&lt;/li&gt;
&lt;li&gt;support for database views (or maybe just entities representing SQL expressions)&lt;/li&gt;
&lt;li&gt;more drivers — namely better-sqlite3 and cockroach sounds like low hanging fruit, given knex now supports those natively&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Like&lt;/em&gt; &lt;a href="https://mikro-orm.io/" rel="noopener noreferrer"&gt;&lt;em&gt;MikroORM&lt;/em&gt;&lt;/a&gt;&lt;em&gt;? ⭐️&lt;/em&gt; &lt;a href="https://github.com/mikro-orm/mikro-orm" rel="noopener noreferrer"&gt;&lt;em&gt;Star it&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on GitHub and share this article with your friends. If you want to support the project financially, you can do so via&lt;/em&gt; &lt;a href="https://github.com/sponsors/B4nan" rel="noopener noreferrer"&gt;&lt;em&gt;GitHub Sponsors&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>database</category>
      <category>node</category>
    </item>
    <item>
      <title>MikroORM 4.1: Let’s talk about performance</title>
      <dc:creator>Martin Adámek</dc:creator>
      <pubDate>Tue, 13 Oct 2020 13:13:34 +0000</pubDate>
      <link>https://dev.to/b4nan/mikroorm-4-1-let-s-talk-about-performance-2idi</link>
      <guid>https://dev.to/b4nan/mikroorm-4-1-let-s-talk-about-performance-2idi</guid>
      <description>&lt;p&gt;I just shipped version 4.1 of &lt;a href="https://github.com/mikro-orm/mikro-orm"&gt;MikroORM&lt;/a&gt;, the TypeScript ORM for Node.js, and I feel like this particular release deserves a bit more attention than a regular feature release.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KAVaQRF9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/725/0%2AR2CETMgg1344gf0V.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KAVaQRF9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/725/0%2AR2CETMgg1344gf0V.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In case you don’t know…
&lt;/h3&gt;

&lt;p&gt;If you never heard of &lt;a href="https://github.com/mikro-orm/mikro-orm"&gt;MikroORM&lt;/a&gt;, it’s a TypeScript data-mapper ORM with Unit of Work and Identity Map. It supports MongoDB, MySQL, PostgreSQL and SQLite drivers currently. Key features of the ORM are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#implicit-transactions"&gt;Implicit transactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#changeset-based-persistence"&gt;ChangeSet based persistence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/identity-map/"&gt;Identity map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z7uH4rXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AzPahC74XliMguexT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z7uH4rXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AzPahC74XliMguexT.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the full &lt;a href="https://medium.com/dailyjs/introducing-mikro-orm-typescript-data-mapper-orm-with-identity-map-9ba58d049e02"&gt;introductory article here&lt;/a&gt; or &lt;a href="https://mikro-orm.io/"&gt;browse through the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what changed?
&lt;/h3&gt;

&lt;p&gt;This release had only one clear goal in mind — the performance. It all started with &lt;a href="https://github.com/mikro-orm/mikro-orm/issues/732"&gt;an issue&lt;/a&gt; pointing out that flushing 10k entities in a single unit of work is very slow. While this kind of use case was never a target for me, I started to see all the possibilities the Unit of Work pattern offers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch inserts, updates and deletes
&lt;/h3&gt;

&lt;p&gt;The biggest performance killer was the amount of queries — even if the query is as simple and optimised as possible, firing 10k of those will be always quite slow. For inserts and deletes, it was quite trivial to group all the queries. A bit more challenging were the updates — to batch those, MikroORM now uses case statements.&lt;/p&gt;

&lt;p&gt;As a result, when you now flush changes made to one entity type, only one query per given operation (create/update/delete) will be executed. This brings significant difference, as we are now executing fixed number of queries (in fact the changes are batched in chunks of 300 items).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  JIT compilation
&lt;/h3&gt;

&lt;p&gt;Second important change in 4.1 is JIT compilation. Under the hood, MikroORM now first generates simple functions for comparing and hydrating entities, that are tailored to their metadata definition. The main difference is that those generated functions are accessing the object properties directly (e.g. o.name), instead of dynamically (e.g. o[prop.name]), as all the information from metadata are inlined there. This allows V8 to better understand the code so it is able to run it faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;Here are the results for a simple 10k entities benchmark:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ayv6z1fG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AaROevToSrzcQdPsPzXYnSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ayv6z1fG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AaROevToSrzcQdPsPzXYnSQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In average, inserting 10k entities takes around 70ms with sqlite, updates are a tiny bit slower. You can see results for other drivers here: &lt;a href="https://github.com/mikro-orm/benchmark"&gt;https://github.com/mikro-orm/benchmark&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SPIs72Ia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/400/0%2A2WaopAkejC3T6213.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SPIs72Ia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/400/0%2A2WaopAkejC3T6213.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Acknowledgement
&lt;/h3&gt;

&lt;p&gt;Kudos to &lt;a href="https://github.com/marcj"&gt;Marc J. Schmidt&lt;/a&gt;, the author of the initial issue, as without his help this would probably never happen, or at least not in near future. Thanks a lot!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Like&lt;/em&gt; &lt;a href="https://mikro-orm.io/"&gt;&lt;em&gt;MikroORM&lt;/em&gt;&lt;/a&gt;&lt;em&gt;? ⭐️&lt;/em&gt; &lt;a href="https://github.com/mikro-orm/mikro-orm"&gt;&lt;em&gt;Star it&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on GitHub and share this article with your friends. If you want to support the project financially, you can do so via&lt;/em&gt; &lt;a href="https://github.com/sponsors/B4nan"&gt;&lt;em&gt;GitHub Sponsors&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>database</category>
      <category>node</category>
    </item>
    <item>
      <title>MikroORM 4: Filling the Gaps</title>
      <dc:creator>Martin Adámek</dc:creator>
      <pubDate>Tue, 08 Sep 2020 19:30:04 +0000</pubDate>
      <link>https://dev.to/b4nan/mikroorm-4-filling-the-gaps-2a0g</link>
      <guid>https://dev.to/b4nan/mikroorm-4-filling-the-gaps-2a0g</guid>
      <description>&lt;p&gt;After 4 months of active development, I am thrilled to announce the release of &lt;a href="http://github.com/mikro-orm/mikro-orm"&gt;MikroORM 4&lt;/a&gt;. When I started to work on v4, the goal was to make it relatively small release, mainly to drop support for TypeScript 3.6 and Node.js 8, and to split the project into multiple packages, so we can have more fine grained control over the dependencies (mainly because of ts-morph having TS as a runtime dependency).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But what a major release would that be, without having a bunch of new features as well, right?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UAeRWIis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AJU7VN0bgkL57RnZJ" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UAeRWIis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AJU7VN0bgkL57RnZJ" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@ryoji__iwata?utm_source=medium&amp;amp;utm_medium=referral"&gt;Ryoji Iwata&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In case you don’t know…
&lt;/h3&gt;

&lt;p&gt;If you never heard of &lt;a href="https://github.com/mikro-orm/mikro-orm"&gt;MikroORM&lt;/a&gt;, it’s a TypeScript data-mapper ORM with Unit of Work and Identity Map. It supports MongoDB, MySQL, PostgreSQL and SQLite drivers currently. Key features of the ORM are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#implicit-transactions"&gt;Implicit transactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#changeset-based-persistence"&gt;ChangeSet based persistence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/identity-map/"&gt;Identity map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ByXWpvPR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AVEfH0Y8e_cMVXad1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ByXWpvPR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AVEfH0Y8e_cMVXad1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the full &lt;a href="https://medium.com/dailyjs/introducing-mikro-orm-typescript-data-mapper-orm-with-identity-map-9ba58d049e02"&gt;introductory article here&lt;/a&gt; or &lt;a href="https://mikro-orm.io/"&gt;browse through the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick summary of 3.x releases
&lt;/h3&gt;

&lt;p&gt;Before I dive into all the things v4, let’s recap the major features that landed in 3.x releases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/entity-schema"&gt;Defining entities via&lt;/a&gt;&lt;a href="https://mikro-orm.io/docs/entity-schema"&gt;EntitySchema&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/propagation"&gt;Propagation of changes to m:1/1:1 to inverse sides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/usage-with-mongo#transactions"&gt;Transactions in MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/composite-keys"&gt;Composite primary keys&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Monorepo
&lt;/h3&gt;

&lt;p&gt;The first major change I want to talk about is the split into multiple packages. As mentioned above, the biggest motivation for this change was to get rid of TS as a runtime dependency, when it is not needed. Another nice example is knex, which is used as a base layer for SQL driver, but has no meaning for mongodb users. Lastly, it turned out Highlight.js, that was used for query highlighting, is also quite fat and slow, so I ended up writing custom highlighters that are built for CLI and are (almost) dependency free.&lt;/p&gt;

&lt;p&gt;In v4, there are 12 packages and 2 highlighters, you install only what you use, and you have control over what is needed in production and what is just a dev dependency. This is especially useful for serverless users, where cold start speeds matter.&lt;/p&gt;

&lt;p&gt;It felt natural to offer some shortcuts on the EntityManager and EntityRepository level, so we now have flavours of those classes in place, that offer things like em.execute(sql) or em.aggregate(). To access those driver specific methods, be sure to use the classes from driver packages:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Database connectors like pg or sqlite3 are now dependencies of the driver packages (e. g. @mikro-orm/sqlite).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Filters&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Probably the most interesting feature of v4 are &lt;a href="https://mikro-orm.io/docs/filters/"&gt;filters&lt;/a&gt;, also known as association scopes. They allow you to define data visibility rules, both global and bound to entity. One common application of filters are soft deletes, or automatic tenant conditions.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Filters are applied to those methods of EntityManager: find(), findOne(), findAndCount(), findOneOrFail(), count(), nativeUpdate() and nativeDelete(). Filters can be parametric, the parameter can be also in form of callback (possibly async). You can also make the filter enabled by default.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Filter can be defined at the entity level, dynamically via EM (global filters) or in the ORM configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Global Filters
&lt;/h4&gt;

&lt;p&gt;We can also register filters dynamically via EntityManager API. We call such filters global. They are enabled by default (unless disabled via last parameter in addFilter() method), and applied to all entities. You can limit the global filter to only specified entities.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Filters as well as filter params set on the EM will be copied to all its forks.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;EventSubscribers and flush events&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As opposed to regular lifecycle hooks, we can now use &lt;a href="https://mikro-orm.io/docs/lifecycle-hooks/#eventsubscriber"&gt;EventSubscriber&lt;/a&gt; to hook to multiple entities or if you do not want to pollute the entity prototype. All methods are optional, if you omit the getSubscribedEntities() method, it means you are subscribing to all entities.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Flush events
&lt;/h4&gt;

&lt;p&gt;There is a &lt;a href="https://mikro-orm.io/docs/lifecycle-hooks/#flush-events"&gt;special kind of events&lt;/a&gt; executed during the commit phase (flush operation). They are executed before, during and after the flush, and they are not bound to any entity in particular.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;beforeFlush is executed before change sets are computed, this is the only event where it is safe to persist new entities.&lt;/li&gt;
&lt;li&gt;onFlush is executed after the change sets are computed.&lt;/li&gt;
&lt;li&gt;afterFlush is executed as the last step just before the flush call resolves. it will be executed even if there are no changes to be flushed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flush event args will not contain any entity instance, as they are entity agnostic. They do contain additional reference to the UnitOfWork instance.&lt;/p&gt;

&lt;p&gt;Following example demonstrates the hidden power of flush events — they allow to hook into the change set tracking, adjusting what will be persisted and how. Here we try to find a CREATE change set for entity FooBar, and if there is any, we automatically create a new FooBaz entity, connecting it to the FooBar one. This kind of operations was previously impossible, as in regular lifecycle hooks we can only adjust the entity that triggers the event.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Joined loading strategy
&lt;/h3&gt;

&lt;p&gt;Loading of complex relations now support so called &lt;a href="https://mikro-orm.io/docs/loading-strategies/"&gt;JOINED strategy&lt;/a&gt;. Its name is quite self-explanatory — instead of the default (SELECT_IN) strategy, it uses single SQL query and maps the result to multiple entities.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Single Table Inheritance&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mikro-orm.io/docs/inheritance-mapping/#single-table-inheritance"&gt;STI is an inheritance mapping strategy&lt;/a&gt; where all classes of a hierarchy are mapped to a single database table. In order to distinguish which row represents which type in the hierarchy a so-called discriminator column is used.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If no discriminator map is provided, it will be generated automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Following example defines 3 entities — they will all be stored in a single database table called person, with a special column named type, that will be used behind the scenes to know what class should be used to represent given row/entity.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Embeddables&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mikro-orm.io/docs/embeddables/"&gt;Embeddables&lt;/a&gt; are classes which are not entities themselves, but are embedded in entities and can also be queried. You’ll mostly want to use them to reduce duplication or separating concerns. Value objects such as date range or address are the primary use case for this feature.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Embeddables can only contain properties with basic @Property() mapping.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Following example will result in a single database table, where the address fields will be inlined (with prefix) to the user table.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Lazy scalar properties&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In MikroORM 4, we can mark any property as &lt;a href="https://mikro-orm.io/docs/defining-entities#lazy-scalar-properties"&gt;lazy: true&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;When we need such value, we can use populate parameter to load it as if it was a reference.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the entity is already loaded and you need to populate a lazy scalar property, you might need to pass refresh: true in the FindOptions.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Computed Properties&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Another small enhancement in entity definition is the &lt;a href="https://mikro-orm.io/docs/defining-entities/#formulas"&gt;@Formula() decorator&lt;/a&gt;. It 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.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Type-safe references&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Next feature I would like to mention is rather hidden, and is a bit experimental. In MikroORM 4, all EntityManager and EntityRepository methods for querying entities (e.g. find()) will now return special Loaded type, where we automatically infer what relations are populated. It dynamically adds special get() method to both Reference and Collection instances, that you can use to ensure the relation is loaded on the type level.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;QueryBuilder improvements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There have been quite a lot of small adjustments in QueryBuilder, to name a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;support for subqueries and qb.ref()&lt;/li&gt;
&lt;li&gt;using sql snippets with qb.raw()&lt;/li&gt;
&lt;li&gt;pagination support via subselects (QueryFlag.PAGINATE)&lt;/li&gt;
&lt;li&gt;update &amp;amp; delete queries with auto-joining&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are few examples of those features in action:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;And many many more…&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;em.begin/commit/rollback() methods are back&lt;/li&gt;
&lt;li&gt;using file globs for discovery (**/*.entity.ts)&lt;/li&gt;
&lt;li&gt;custom driver exceptions (UniqueConstraintViolationException, …)&lt;/li&gt;
&lt;li&gt;adding items to not-initialized collections&lt;/li&gt;
&lt;li&gt;bulk deletes and other performance improvements&lt;/li&gt;
&lt;li&gt;inference of custom repository type (EntityRepositoryType)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/serializing#property-serializers"&gt;property serializers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href="https://github.com/mikro-orm/mikro-orm/blob/master/CHANGELOG.md"&gt;changelog&lt;/a&gt; for full list of new features and fixes.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;More example integrations&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Koa: &lt;a href="https://github.com/mikro-orm/koa-ts-example-app"&gt;https://github.com/mikro-orm/koa-ts-example-app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GraphQL: &lt;a href="https://github.com/driescroons/mikro-orm-graphql-example"&gt;https://github.com/driescroons/mikro-orm-graphql-example&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Serverless: &lt;a href="https://github.com/thomaschaaf/serverless-mikro-orm-example-app"&gt;https://github.com/thomaschaaf/serverless-mikro-orm-example-app&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Upgrading
&lt;/h3&gt;

&lt;p&gt;For smooth upgrading, read the full &lt;a href="https://mikro-orm.io/docs/upgrading-v3-to-v4"&gt;upgrading guide&lt;/a&gt;. Here are few notable breaking changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default metadata provider is ReflectMetadataProvider, to use ts-morph, you need to install it from @mikro-orm/reflection and explicitly provide it in the ORM configuration. If you want to use ReflectMetadataProvider, be sure to see the &lt;a href="https://mikro-orm.io/docs/metadata-providers/#limitations-and-requirements"&gt;list of its limitations&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;TsMorphMetadataProvider now uses *.d.ts files in production mode, so be sure to enable them in your tsconfig.json.&lt;/li&gt;
&lt;li&gt;@mikro-orm/core package is not dependent on knex, and therefore cannot provide methods like createQueryBuilder() — instead, those methods exist on SqlEntityManager. You can import it from the driver package, e.g. import { EntityManager } from '@mikro-orm/mysql;.&lt;/li&gt;
&lt;li&gt;To use CLI, you need to install @mikro-orm/cli package.&lt;/li&gt;
&lt;li&gt;When using folder based discovery, the options entitiesDirs and entitiesDirsTs are now removed in favour of entities and entitiesTs. You can now mix entity references with folders and file globs, negative globs are also supported.&lt;/li&gt;
&lt;li&gt;For Nest.js users, there is a new &lt;a href="https://github.com/mikro-orm/nestjs"&gt;@mikro-orm/nestjs&lt;/a&gt; package, which is a fork of the &lt;a href="https://github.com/dario1985/nestjs-mikro-orm"&gt;nestjs-mikro-orm&lt;/a&gt; module with changes needed for
MikroORM 4.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What’s next?
&lt;/h3&gt;

&lt;p&gt;Here are some features I’d like to work on in the near future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improved schema diffing&lt;/li&gt;
&lt;li&gt;ts-morph reflection via custom TS compiler plugin&lt;/li&gt;
&lt;li&gt;Query caching&lt;/li&gt;
&lt;li&gt;MS SQL Server support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  WDYT?
&lt;/h3&gt;

&lt;p&gt;So thit is MikroORM 4, what do you think about it? What features or changes would you like to see next? Or what part of the documentation should be improved and how?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Like&lt;/em&gt; &lt;a href="https://mikro-orm.io/"&gt;&lt;em&gt;MikroORM&lt;/em&gt;&lt;/a&gt;&lt;em&gt;? ⭐️&lt;/em&gt; &lt;a href="https://github.com/mikro-orm/mikro-orm"&gt;&lt;em&gt;Star it&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on GitHub and share this article with your friends. If you want to support the project financially, you can do so via&lt;/em&gt; &lt;a href="https://github.com/sponsors/B4nan"&gt;&lt;em&gt;GitHub Sponsors&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>node</category>
      <category>oop</category>
    </item>
    <item>
      <title>MikroORM 3: Knex.js, CLI, Schema Updates, Entity Generator and more…</title>
      <dc:creator>Martin Adámek</dc:creator>
      <pubDate>Thu, 16 Jan 2020 16:27:43 +0000</pubDate>
      <link>https://dev.to/b4nan/mikroorm-3-knex-js-cli-schema-updates-entity-generator-and-more-3g56</link>
      <guid>https://dev.to/b4nan/mikroorm-3-knex-js-cli-schema-updates-entity-generator-and-more-3g56</guid>
      <description>&lt;p&gt;New major version of the TypeScript ORM has been released, read about its new features and breaking changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  In case you don’t know…
&lt;/h3&gt;

&lt;p&gt;If you never heard of &lt;a href="https://github.com/mikro-orm/mikro-orm" rel="noopener noreferrer"&gt;MikroORM&lt;/a&gt;, it’s a TypeScript data-mapper ORM with Unit of Work and Identity Map. It supports MongoDB, MySQL, PostgreSQL and SQLite drivers currently. Key features of the ORM are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#implicit-transactions" rel="noopener noreferrer"&gt;Implicit transactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mikro-orm/mikro-orm#changeset-based-persistence" rel="noopener noreferrer"&gt;ChangeSet based persistence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/identity-map/" rel="noopener noreferrer"&gt;Identity map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A0eZmw4DceSltEEQh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A0eZmw4DceSltEEQh.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the full &lt;a href="https://medium.com/dailyjs/introducing-mikro-orm-typescript-data-mapper-orm-with-identity-map-9ba58d049e02" rel="noopener noreferrer"&gt;introductory article here&lt;/a&gt; or &lt;a href="https://mikro-orm.io" rel="noopener noreferrer"&gt;browse through the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrated Knex.js
&lt;/h3&gt;

&lt;p&gt;You probably know Knex.js already, but if you don’t, it is a “batteries included” SQL query builder for &lt;strong&gt;Postgres&lt;/strong&gt; , &lt;strong&gt;MSSQL&lt;/strong&gt; , &lt;strong&gt;MySQL&lt;/strong&gt; , &lt;strong&gt;MariaDB&lt;/strong&gt; , &lt;strong&gt;SQLite3&lt;/strong&gt; , &lt;strong&gt;Oracle&lt;/strong&gt; , and &lt;strong&gt;Amazon Redshift&lt;/strong&gt; designed to be flexible, portable, and fun to use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F649%2F0%2AFHWIwC9WTwl2hkQ7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F649%2F0%2AFHWIwC9WTwl2hkQ7.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Knex.js is now used as both a query builder and a query runner for all SQL drivers. This allows to simplify SQL driver implementations as well as brings some new possibilities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Knex.js
&lt;/h4&gt;

&lt;p&gt;You can access configured knex instance via qb.getKnexQuery() method. Then you can execute it via the Connection.execute() and map the results via EntityManager.map().&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can also get clear and configured knex instance from the connection via getKnex() method. As this method is not available on the base Connection class, you will need to either manually type cast the connection to AbstractSqlConnection (or the actual implementation you are using, e.g. MySqlConnection), or provide correct driver type hint to your EntityManager instance, which will be then automatically inferred in em.getConnection() method.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Driver and connection implementations are not directly exported from mikro-orm module. You can import them from mikro-orm/dist (e.g. import { PostgreSqlDriver } from 'mikro-orm/dist/drivers/PostgreSqlDriver').&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Connection Pooling
&lt;/h4&gt;

&lt;p&gt;With Knex.js used as a query runner, support for connection pooling is finally available. &lt;a href="https://github.com/vincit/tarn.js" rel="noopener noreferrer"&gt;Tarn.js&lt;/a&gt; is used for this internally, using connection pool with min: 2, max: 10 for the MySQL and PG libraries, and a single connection for sqlite3 by default. Use pool option to change this when initializing the ORM.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  More SQL Drivers?
&lt;/h4&gt;

&lt;p&gt;One of the strongest reasons to integrate Knex.js was that it allows to simplify and unify SQL drivers and opens doors for implementing new SQL drivers. Knex.js currently supports (apart from those currently supported by MikroORM): MSSQL, Oracle and Amazon Redshift.&lt;/p&gt;

&lt;p&gt;Thanks to AbstractSqlDriver and AbstractSqlConnection classes it should be fairly simple to implement them. I am open for PRs for those drivers, as I would like to focus on developing new ORM features mainly, instead of learning new SQL dialects I have never used. I will be happy to assist to anybody interested — feel free to reach me out either via Slack, email or GitHub issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplified Entity Definition
&lt;/h3&gt;

&lt;p&gt;Now it is no longer needed to merge entities with IEntity interface, that was polluting entity's interface with internal methods. New interfaces IdentifiedEntity&amp;lt;T&amp;gt;, UuidEntity&amp;lt;T&amp;gt; and MongoEntity&amp;lt;T&amp;gt; are introduced, that should be implemented by entities. They are not adding any new properties or methods, keeping the entity's interface clean.&lt;/p&gt;

&lt;p&gt;IEntity interface has been renamed to AnyEntity&amp;lt;T, PK&amp;gt; and it no longer has public methods like toJSON(), toObject() or init(). One can use wrap() method provided by ORM that will enhance property type when needed with those methods (e.g. await wrap(book.author).init()). To keep all methods available on the entity, you can still use interface merging with WrappedEntity&amp;lt;T, PK&amp;gt; that both extends AnyEntity&amp;lt;T, PK&amp;gt; and defines all those methods.&lt;/p&gt;

&lt;p&gt;You will need to mark the entity by implementing one of *Entity interfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IdEntity&amp;lt;T&amp;gt; for numeric/string PK on id property (id: number)&lt;/li&gt;
&lt;li&gt;UuidEntity&amp;lt;T&amp;gt; for string PK on uuid property (uuid: string)&lt;/li&gt;
&lt;li&gt;MongoEntity&amp;lt;T&amp;gt; for mongo, where id: string and _id: ObjectId are required&lt;/li&gt;
&lt;li&gt;AnyEntity&amp;lt;T, PK&amp;gt; for other possible properties (fill the PK property name to PK parameter, e.g.: AnyEntity&amp;lt;Book, 'myPrimaryProperty'&amp;gt;')&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To keep all public methods that were part of IEntity interface in v2, you can use &lt;a href="https://mikro-orm.io/docs/defining-entities#using-wrappedentity-interface" rel="noopener noreferrer"&gt;WrappedEntity&amp;lt;T, PK&amp;gt; via interface merging&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested Queries
&lt;/h3&gt;

&lt;p&gt;SQL driver now support nested where and orderBy conditions. This means that you can query by properties of a relationship and the relation will be automatically joined for you. They are available both in EntityManager and QueryBuilder APIs.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Strict Typing of Queries
&lt;/h3&gt;

&lt;p&gt;Previously the where parameter of EntityManager’s find methods (find(), findOne(), count()) was weakly typed. It allowed users to pass pretty much anything there.&lt;/p&gt;

&lt;p&gt;Now the query is strictly typed, only entity properties and operators can be used and the type of property value is also checked.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Improved Schema Generator
&lt;/h3&gt;

&lt;p&gt;SchemaGenerator now supports creating, updating and dropping the schema. You can either get the SQL queries as array of strings or directly run them on the database.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Always check the generated SQL first before running it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is also new columnType property attribute you can use to specify the database specific column type explicitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrations
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F628%2F0%2Ab3RWZY_ROCrJs3RE.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F628%2F0%2Ab3RWZY_ROCrJs3RE.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Better way to handle schema updates than using the SchemaGenerator directly is to use Migrations. MikroORM 3 has &lt;a href="https://mikro-orm.io/docs/migrations" rel="noopener noreferrer"&gt;integrated support for migrations&lt;/a&gt; via &lt;a href="https://github.com/sequelize/umzug" rel="noopener noreferrer"&gt;umzug&lt;/a&gt;. It allows you to generate migrations with current schema differences.&lt;/p&gt;

&lt;p&gt;By default, each migration will be all executed inside a transaction, and all of them will be wrapped in one master transaction, so if one of them fails, everything will be rolled back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating Entities from Current Database
&lt;/h3&gt;

&lt;p&gt;As a counterpart to the SchemaGenerator that propagates changes in your entities to the database schema, there is now &lt;a href="https://mikro-orm.io/docs/entity-generator" rel="noopener noreferrer"&gt;EntityGenerator&lt;/a&gt; to help you with reverse engineering current database schema and creating entities based on it.&lt;/p&gt;

&lt;p&gt;It supports basic entity definition including ManyToOne and OneToOne relationships. Currently ManyToMany will be generated as additional entity with two ManyToOne relations and you will need to refactor this yourself.&lt;/p&gt;

&lt;p&gt;While it can help a lot, there is quite a lot of room for improvement. In future I would like to implement proper support for ManyToMany relations as well for enums and indexes. Another possible extension would be to allow editing existing entities (syncing them with current schema).&lt;/p&gt;

&lt;h3&gt;
  
  
  CLI
&lt;/h3&gt;

&lt;p&gt;While you can use SchemaGenerator and EntityGenerator manually, much easier way is to use &lt;a href="https://mikro-orm.io/docs/installation#setting-up-the-commandline-tool" rel="noopener noreferrer"&gt;new CLI tool&lt;/a&gt;. Simply create configuration file in root directory or add its path to package.json. TypeScript files are also supported via ts-node:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now you can use the CLI with help of &lt;a href="https://github.com/npm/npx" rel="noopener noreferrer"&gt;npx&lt;/a&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To verify your setup, you can use the mikro-orm debug command. Once you have it configured properly, you can also re-use it when initializing the ORM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// when no options parameter is provided, CLI config will be used
const orm = await MikroORM.init();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Custom Mapping Types
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F500%2F0%2AzAn0BtH_iz7b8Ywj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F500%2F0%2AzAn0BtH_iz7b8Ywj.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://mikro-orm.io/docs/custom-types/" rel="noopener noreferrer"&gt;Custom Types&lt;/a&gt; we can now enhance how the database value will be represented in the ORM. You can define custom types by extending Type abstract class, it has 4 optional methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;convertToDatabaseValue(value: any, platform: Platform): any&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Converts a value from its JS representation to its database representation of this type. By default returns unchanged value.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;convertToJSValue(value: any, platform: Platform): any&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Converts a value from its database representation to its JS representation of this type. By default returns unchanged value.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;toJSON(value: any, platform: Platform): any&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Converts a value from its JS representation to its serialized JSON form of this type. By default converts to the database value.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;getColumnType(prop: EntityProperty, platform: Platform): string&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gets the SQL declaration snippet for a field of this type. By default returns columnType of given property.&lt;/p&gt;

&lt;p&gt;Here is a simplified version of DateType that is already present in the ORM:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  And Many More…
&lt;/h3&gt;

&lt;p&gt;There are many more new features, see the &lt;a href="https://github.com/mikro-orm/mikro-orm/blob/master/CHANGELOG.md" rel="noopener noreferrer"&gt;changelog&lt;/a&gt; to read the full list. Here are few of them worth mentioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/entity-references/" rel="noopener noreferrer"&gt;Improved support for References&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/defining-entities/#enums" rel="noopener noreferrer"&gt;Navite Enum support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/entity-manager#fetching-paginated-results" rel="noopener noreferrer"&gt;em.findAndCount()&lt;/a&gt; and &lt;a href="https://mikro-orm.io/docs/entity-manager#handling-not-found-entities" rel="noopener noreferrer"&gt;em.findOneOrFail()&lt;/a&gt; methods&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mikro-orm.io/docs/metadata-providers/#reflectmetadataprovider" rel="noopener noreferrer"&gt;ReflectMetadataProvider&lt;/a&gt; as a fast alternative to ts-morph reflection&lt;/li&gt;
&lt;li&gt;Improved logging with query highlighting&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/deployment/#deploy-a-bundle-of-entities-and-dependencies-with-webpack" rel="noopener noreferrer"&gt;Support for bundling via Webpack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Eager loading&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mikro-orm.io/docs/read-connections" rel="noopener noreferrer"&gt;Read Connections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;More strict entity definition validation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Notable Breaking Changes
&lt;/h3&gt;

&lt;p&gt;Here is a short list of breaking changes. You can see the full list in the docs: &lt;a href="https://mikro-orm.io/docs/upgrading-v2-to-v3/" rel="noopener noreferrer"&gt;https://mikro-orm.io/docs/upgrading-v2-to-v3/&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Auto-flushing Disabled by Default
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you had&lt;/em&gt; &lt;em&gt;autoFlush: false in your ORM configuration before, you can now remove this line, no changes are needed in your app.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Default value for autoFlush is now 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 as it can cause unwanted small transactions being created around each persist.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Transactions API
&lt;/h4&gt;

&lt;p&gt;Transactions now require using em.transactional() method, previous methods beginTransaction/commit/rollback are now removed.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Making it a bit more Professional…
&lt;/h3&gt;

&lt;p&gt;Not a big deal, but probably worth mentioning — MikroORM’s repository has been transferred to new &lt;a href="https://github.com/mikro-orm" rel="noopener noreferrer"&gt;MikroORM GitHub Organization&lt;/a&gt; and the website is now moved to &lt;a href="https://mikro-orm.io" rel="noopener noreferrer"&gt;mikro-orm.io&lt;/a&gt;. Old links should be properly redirected, if you find some 404, please let me know thru GitHub issues!&lt;/p&gt;

&lt;p&gt;Website has also been redesigned — now it is built with Docusaurus (v2) and provides fulltext search by Algolia. The docs are now also &lt;a href="https://mikro-orm.io/versions" rel="noopener noreferrer"&gt;versioned&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mikro-orm.io" rel="noopener noreferrer"&gt;Check it out!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2pdwLgyPZNltJQ_2j8poSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2pdwLgyPZNltJQ_2j8poSQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s next?
&lt;/h3&gt;

&lt;p&gt;Here are some features I am planning to work in the near future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Composite primary keys&lt;/li&gt;
&lt;li&gt;Transactions in MongoDB&lt;/li&gt;
&lt;li&gt;Complex hydration of joined result sets&lt;/li&gt;
&lt;li&gt;Slow query log&lt;/li&gt;
&lt;li&gt;M:N support in entity generator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also some interesting suggestion in the Github issues, like &lt;a href="https://github.com/mikro-orm/mikro-orm/issues/266" rel="noopener noreferrer"&gt;Dataloader integration&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  WDYT?
&lt;/h4&gt;

&lt;p&gt;So that is MikroORM 3, what do you think about it? What features or changes would you like to see next? Or what part of the documentation should be improved and how?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Like&lt;/em&gt; &lt;a href="https://mikro-orm.io" rel="noopener noreferrer"&gt;&lt;em&gt;MikroORM&lt;/em&gt;&lt;/a&gt;&lt;em&gt;? ⭐️&lt;/em&gt; &lt;a href="https://github.com/mikro-orm/mikro-orm" rel="noopener noreferrer"&gt;&lt;em&gt;Star it&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on GitHub and share this article with your friends.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>node</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Handling transactions and concurrency in MikroORM</title>
      <dc:creator>Martin Adámek</dc:creator>
      <pubDate>Tue, 18 Jun 2019 17:44:12 +0000</pubDate>
      <link>https://dev.to/b4nan/handling-transactions-and-concurrency-in-mikroorm-2cfj</link>
      <guid>https://dev.to/b4nan/handling-transactions-and-concurrency-in-mikroorm-2cfj</guid>
      <description>&lt;h2&gt;
  
  
  Wait, what? MikroORM?
&lt;/h2&gt;

&lt;p&gt;If you never heard of &lt;a href="https://github.com/B4nan/mikro-orm"&gt;MikroORM&lt;/a&gt;, it’s a TypeScript data-mapper ORM with Unit of Work and Identity Map. It supports MongoDB, MySQL, PostgreSQL and SQLite drivers currently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SL7QlMOB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2A_WcU6mEj971G2xrIkr7duQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SL7QlMOB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2A_WcU6mEj971G2xrIkr7duQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the full &lt;a href="https://dev.to/b4nan/introducing-mikroorm-typescript-data-mapper-orm-with-identity-map-pc8"&gt;introductory article here&lt;/a&gt; or &lt;a href="https://b4nan.github.io/mikro-orm/"&gt;browse through the docs&lt;/a&gt;. The project is under active development, so be sure to check out the &lt;a href="https://github.com/B4nan/mikro-orm/blob/master/CHANGELOG.md"&gt;change log&lt;/a&gt; as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MikroORM is heavily inspired by &lt;a href="https://www.doctrine-project.org/"&gt;Doctrine&lt;/a&gt; ORM. This article is highly inspired by &lt;a href="https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html"&gt;doctrine documentation&lt;/a&gt; as the behaviour in MikroORM is pretty much the same. All credits for the general explanation of this topic goes to them!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Note about persisting
&lt;/h2&gt;

&lt;p&gt;There are 2 methods we should first describe to understand how persisting works in MikroORM: &lt;code&gt;em.persist()&lt;/code&gt; and &lt;code&gt;em.flush()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;em.persist(entity, flush?: boolean)&lt;/code&gt; is used to mark new entities for future persisting. It will make the entity managed by given &lt;code&gt;EntityManager&lt;/code&gt; and once &lt;code&gt;flush&lt;/code&gt; will be called, it will be written to the database. Second boolean parameter can be used to invoke &lt;code&gt;flush&lt;/code&gt; immediately. Its default value is configurable via &lt;code&gt;autoFlush&lt;/code&gt; option.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Default value of &lt;code&gt;autoFlush&lt;/code&gt; is currently set to &lt;code&gt;true&lt;/code&gt;, which will change in upcoming major release. Users are encouraged to either set &lt;code&gt;autoFlush&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; or use &lt;code&gt;em.persistLater()&lt;/code&gt; (equal to &lt;code&gt;em.persist(entity, false)&lt;/code&gt;) and &lt;code&gt;em.persistAndFlush()&lt;/code&gt; methods instead. Every time persisting is mentioned in this article, it is with &lt;code&gt;autoFlush&lt;/code&gt; set to &lt;code&gt;false&lt;/code&gt; in mind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand &lt;code&gt;flush&lt;/code&gt;, lets first define what managed entity is: An entity is managed if it’s fetched from the database (via &lt;code&gt;em.find()&lt;/code&gt;, &lt;code&gt;em.findOne()&lt;/code&gt; or via other managed entity) or registered as new through &lt;code&gt;em.persist()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;em.flush()&lt;/code&gt; will go through all managed entities, compute appropriate change sets and perform according database queries. As an entity loaded from database becomes managed automatically, you do not have to call &lt;code&gt;persist&lt;/code&gt; on those, and &lt;code&gt;flush&lt;/code&gt; is enough to update them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tpJsvcXa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AEo5JP9abOfPV24Uf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tpJsvcXa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AEo5JP9abOfPV24Uf.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Transaction demarcation
&lt;/h2&gt;

&lt;p&gt;Transaction demarcation is the task of defining your transaction boundaries. For the most part, MikroORM already takes care of proper transaction demarcation for you: All the write operations (INSERT/UPDATE/DELETE) are queued until &lt;code&gt;em.flush()&lt;/code&gt; is invoked which wraps all of these changes in a single transaction. However, MikroORM also allows (and encourages) you to take over and control transaction demarcation yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 1: Implicitly
&lt;/h3&gt;

&lt;p&gt;The first approach is to use the implicit transaction handling provided by the MikroORM &lt;code&gt;EntityManager&lt;/code&gt;. Given the following code snippet, without any explicit transaction demarcation:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Since we do not do any custom transaction demarcation in the above code, &lt;code&gt;em.flush()&lt;/code&gt; will begin and commit/rollback a transaction. This is sufficient if all the data manipulation that is part of a unit of work happens through the domain model and thus the ORM — in other words, unless you run some write queries manually, via &lt;code&gt;QueryBuilder&lt;/code&gt;, or use one of &lt;code&gt;em.nativeInsert/Update/Delete&lt;/code&gt; helpers.&lt;/p&gt;

&lt;p&gt;Here is a bit more complex example where multiple entities are involved:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We load one author by id, all his books and their tags as well as their publisher. For simplicity, let’s assume the author has one book associated, which has one book tag and one publisher.&lt;/p&gt;

&lt;p&gt;Then we update multiple things on book of that author, editing name of the tag, adding new one, and changing publisher’s name. As we are working with already managed entities (retrieved from &lt;code&gt;EntityManager&lt;/code&gt;), we can simply &lt;code&gt;flush&lt;/code&gt; without needing to &lt;code&gt;persist&lt;/code&gt; those entities.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;flush&lt;/code&gt; call here will compute all differences and run database queries accordingly. They will all be encapsulated in a transaction, as you can see from following list of fired queries:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Approach 2: Explicitly
&lt;/h3&gt;

&lt;p&gt;The explicit alternative is to use the transactions API directly to control the boundaries. The code then looks like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Explicit transaction demarcation is required when you want to include custom DBAL operations in a unit of work (e.g. when firing native SQL UPDATE queries) or when you want to make use of some methods of the &lt;code&gt;EntityManager&lt;/code&gt; API that require an active transaction (e.g. locking) — such methods will throw a &lt;code&gt;ValidationError&lt;/code&gt; to inform you of that requirement.&lt;/p&gt;

&lt;p&gt;A more convenient alternative for explicit transaction demarcation is to use &lt;code&gt;em.transactional(cb)&lt;/code&gt;. It will automatically start the transaction, execute your asynchronous callback and commit it. In case of an exception during those operations, the transaction will be automatically rolled back and the exception will be re-thrown. An example that is functionally equivalent to the previously shown code looks as follows:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the callback parameter, you will get forked &lt;code&gt;EntityManager&lt;/code&gt; that will contain a copy of the current Identity Map. You should use this copy instead of the parent one for all queries inside the transaction. It will be flushed prior to transaction commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exception Handling
&lt;/h3&gt;

&lt;p&gt;When using &lt;em&gt;implicit&lt;/em&gt; transaction demarcation and an exception occurs during &lt;code&gt;em.flush()&lt;/code&gt;, the transaction is automatically rolled back.&lt;/p&gt;

&lt;p&gt;When using &lt;em&gt;explicit&lt;/em&gt; transaction demarcation and an exception occurs, the transaction should be rolled back immediately as demonstrated in the example above. Users are encouraged to use &lt;code&gt;em.transactional(cb)&lt;/code&gt; which will handle that automatically.&lt;/p&gt;

&lt;p&gt;As a result of this procedure, all previously managed or removed instances of the &lt;code&gt;EntityManager&lt;/code&gt; become detached. The state of the detached objects will be the state at the point at which the transaction was rolled back. The state of the objects is in no way rolled back and thus the objects are now out of sync with the database. The application can continue to use the detached objects, knowing that their state is potentially no longer accurate.&lt;/p&gt;

&lt;p&gt;If you intend to start another unit of work after an exception has occurred you should do that with a new &lt;code&gt;EntityManager&lt;/code&gt;. Simply use &lt;code&gt;em.fork()&lt;/code&gt; to obtain fresh copy with cleared identity map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fEkVkxus--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AD4B7hf_Up9bc9wzg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fEkVkxus--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AD4B7hf_Up9bc9wzg.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrency and locking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why we need concurrency control?
&lt;/h3&gt;

&lt;p&gt;If transactions are executed &lt;em&gt;serially&lt;/em&gt; (one at a time), no transaction concurrency exists. However, if concurrent transactions with interleaving operations are allowed, you may easily run into one of those problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The lost update problem&lt;/li&gt;
&lt;li&gt; The dirty read problem&lt;/li&gt;
&lt;li&gt; The incorrect summary problem&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Take a look at &lt;a href="https://www.includehelp.com/dbms/concurrency-and-problem-due-to-concurrency.aspx"&gt;this article&lt;/a&gt; for in-depth explanation of those.&lt;/p&gt;

&lt;p&gt;To mitigate those problems, MikroORM offers support for Pessimistic and Optimistic locking strategies natively. This allows you to take very fine-grained control over what kind of locking is required for your entities in your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimistic Locking
&lt;/h3&gt;

&lt;p&gt;Database transactions are fine for concurrency control during a single request. However, a database transaction should not span across requests, the so-called “user think time”. Therefore a long-running “business transaction” that spans multiple requests needs to involve several database transactions. Thus, database transactions alone can no longer control concurrency during such a long-running business transaction. Concurrency control becomes the partial responsibility of the application itself.&lt;/p&gt;

&lt;p&gt;MikroORM has integrated support for automatic optimistic locking via a version field. In this approach any entity that should be protected against concurrent modifications during long-running business transactions gets a version field that is either a simple number or a Date (timestamp). When changes to such an entity are persisted at the end of a long-running conversation the version of the entity is compared to the version in the database and if they don’t match, a &lt;code&gt;ValidationError&lt;/code&gt; is thrown, indicating that the entity has been modified by someone else already.&lt;/p&gt;

&lt;p&gt;To define a version field, simply use &lt;code&gt;@Property&lt;/code&gt; decorator with &lt;code&gt;version&lt;/code&gt; flag set to &lt;code&gt;true&lt;/code&gt;. Only &lt;code&gt;Date&lt;/code&gt; and &lt;code&gt;number&lt;/code&gt; types are allowed.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Version numbers (not timestamps) should be preferred as they can not potentially conflict in a highly concurrent environment, unlike timestamps where this is a possibility, depending on the resolution of the timestamp on the particular database platform.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When a version conflict is encountered during &lt;code&gt;em.flush()&lt;/code&gt;, a &lt;code&gt;ValidationError&lt;/code&gt; is thrown and the active transaction rolled back (or marked for rollback). This exception can be caught and handled. Potential responses to a &lt;code&gt;ValidationError&lt;/code&gt; are to present the conflict to the user or to refresh or reload objects in a new transaction and then retrying the transaction.&lt;/p&gt;

&lt;p&gt;The time between showing an update form and actually modifying the entity can in the worst scenario be as long as your applications session timeout. If changes happen to the entity in that time frame you want to know directly when retrieving the entity that you will hit an optimistic locking exception.&lt;/p&gt;

&lt;p&gt;You can always verify the version of an entity during a request either when calling &lt;code&gt;em.findOne()&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Or you can use &lt;code&gt;em.lock()&lt;/code&gt; to find out:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Using optimistic locking correctly, you &lt;strong&gt;have&lt;/strong&gt; to pass the version as an additional parameter when updating entity. See following example:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Your frontend app loads an entity from API, the response includes the version property. User makes some changes and fires PUT request back to the API, with version field included in the payload. The PUT handler of the API then reads the version and passes it to the &lt;code&gt;em.findOne()&lt;/code&gt; call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pessimistic Locking
&lt;/h2&gt;

&lt;p&gt;MikroORM supports Pessimistic Locking at the database level. Every Entity can be part of a pessimistic lock, there is no special metadata required to use this feature. Pessimistic Locking requires active transaction, so you will have to use explicit transaction demarcation.&lt;/p&gt;

&lt;p&gt;MikroORM currently supports two pessimistic lock modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Pessimistic Write (&lt;code&gt;LockMode.PESSIMISTIC_WRITE&lt;/code&gt;), locks the underlying database rows for concurrent Read and Write Operations.&lt;/li&gt;
&lt;li&gt;  Pessimistic Read (&lt;code&gt;LockMode.PESSIMISTIC_READ&lt;/code&gt;), locks other concurrent requests that attempt to update or lock rows in write mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use pessimistic locks in three different scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Using &lt;code&gt;em.findOne(className, id, { lockMode  })&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Using &lt;code&gt;em.lock(entity, lockMode)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Using &lt;code&gt;QueryBuilder.setLockMode(lockMode)&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is how it looks like in action:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Like &lt;a href="https://b4nan.github.io/mikro-orm/"&gt;MikroORM&lt;/a&gt;? ⭐️ &lt;a href="https://github.com/B4nan/mikro-orm"&gt;Star it&lt;/a&gt; on GitHub and share this article with your friends.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>node</category>
      <category>sql</category>
    </item>
    <item>
      <title>Introducing MikroORM, TypeScript data-mapper ORM with Identity Map</title>
      <dc:creator>Martin Adámek</dc:creator>
      <pubDate>Tue, 30 Apr 2019 16:40:42 +0000</pubDate>
      <link>https://dev.to/b4nan/introducing-mikroorm-typescript-data-mapper-orm-with-identity-map-pc8</link>
      <guid>https://dev.to/b4nan/introducing-mikroorm-typescript-data-mapper-orm-with-identity-map-pc8</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2j28x75z1r6aih5tab4.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2j28x75z1r6aih5tab4.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;During my early days at university, I remember how quickly I fell in love with object oriented programming and the concepts of &lt;a href="http://hibernate.org/orm/what-is-an-orm/" rel="noopener noreferrer"&gt;Object-relational mapping&lt;/a&gt; and &lt;a href="https://stackoverflow.com/questions/1222392/can-someone-explain-domain-driven-design-ddd-in-plain-english-please/1222488#1222488" rel="noopener noreferrer"&gt;Domain Driven Design&lt;/a&gt;. Back then, I was mainly a PHP programmer (&lt;em&gt;while we did a lot of Java/Hibernate at school&lt;/em&gt;), so a natural choice for me was to start using &lt;a href="https://www.doctrine-project.org/" rel="noopener noreferrer"&gt;Doctrine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A few years ago, when I switched from PHP to Node.js (&lt;em&gt;and later to TypeScript&lt;/em&gt;), I was really confused. How come there is nothing similar to Hibernate or Doctrine in the JavaScript world? About a year ago, I finally came across &lt;a href="https://typeorm.io/" rel="noopener noreferrer"&gt;TypeORM&lt;/a&gt;, and when I read this line in the readme I thought I found what I was looking for:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TypeORM is highly influenced by other ORMs, such as &lt;a href="http://hibernate.org/orm/" rel="noopener noreferrer"&gt;Hibernate&lt;/a&gt;, &lt;a href="http://www.doctrine-project.org/" rel="noopener noreferrer"&gt;Doctrine&lt;/a&gt; and &lt;a href="https://www.asp.net/entity-framework" rel="noopener noreferrer"&gt;Entity Framework&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff78ioqdul99ehqt3qap2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff78ioqdul99ehqt3qap2.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started playing with it immediately, but I got disappointed very quickly. No Identity Map that would keep track of all loaded entities. No Unit of Work that would handle transaction isolation. No unified API for references with very strange support for &lt;a href="https://typeorm.io/#/relations-faq/how-to-use-relation-id-without-joining-relation" rel="noopener noreferrer"&gt;accessing just the identifier without populating the entity&lt;/a&gt;, MongoDB driver (&lt;em&gt;which I was aiming to use&lt;/em&gt;) was experimental and I had a lot problems setting it up. After a few days of struggle, I went away from it.&lt;/p&gt;

&lt;p&gt;By that time, I started to think about writing something myself. And that is how &lt;a href="https://github.com/B4nan/mikro-orm" rel="noopener noreferrer"&gt;&lt;strong&gt;MikroORM&lt;/strong&gt;&lt;/a&gt; started!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5d2kjcwdop2jxcuwogld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5d2kjcwdop2jxcuwogld.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/B4nan/mikro-orm" rel="noopener noreferrer"&gt;MikroORM&lt;/a&gt; is TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Currently it supports &lt;strong&gt;MongoDB&lt;/strong&gt;, &lt;strong&gt;MySQL, PostgreSQL&lt;/strong&gt; and &lt;strong&gt;SQLite&lt;/strong&gt; databases, but more can be supported via &lt;a href="https://b4nan.github.io/mikro-orm/custom-driver/" rel="noopener noreferrer"&gt;custom drivers right now&lt;/a&gt;. It has first class TypeScript support, while staying back compatible with &lt;a href="https://b4nan.github.io/mikro-orm/usage-with-js/" rel="noopener noreferrer"&gt;Vanilla JavaScript&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;First install the module via &lt;code&gt;yarn&lt;/code&gt; or &lt;code&gt;npm&lt;/code&gt; and do not forget to install the database driver as well. Next you will need to enable support for &lt;a href="https://www.typescriptlang.org/docs/handbook/decorators.html" rel="noopener noreferrer"&gt;decorators&lt;/a&gt;&lt;br&gt;&lt;br&gt;
in &lt;code&gt;tsconfig.json&lt;/code&gt; via &lt;code&gt;experimentalDecorators&lt;/code&gt; flag. Then call &lt;code&gt;MikroORM.init&lt;/code&gt; as part of bootstrapping your application.&lt;/p&gt;

&lt;p&gt;Last step is to provide forked &lt;code&gt;EntityManager&lt;/code&gt; for each request, so it will have its own unique &lt;a href="https://b4nan.github.io/mikro-orm/identity-map/" rel="noopener noreferrer"&gt;Identity Map&lt;/a&gt;. To do so, you can use &lt;code&gt;EntityManager.fork()&lt;/code&gt; method. Another way, that is more &lt;a href="https://medium.freecodecamp.org/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f" rel="noopener noreferrer"&gt;DI&lt;/a&gt; friendly, is to create new &lt;a href="https://b4nan.github.io/mikro-orm/identity-map/#request-context" rel="noopener noreferrer"&gt;request context&lt;/a&gt; for each request, which will use some &lt;a href="https://github.com/nodejs/node/blob/master/doc/api/async_hooks.md" rel="noopener noreferrer"&gt;dark magic&lt;/a&gt; in the background to always pick the right &lt;code&gt;EntityManager&lt;/code&gt; for you.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Defining entities
&lt;/h2&gt;

&lt;p&gt;To &lt;a href="https://b4nan.github.io/mikro-orm/defining-entities/" rel="noopener noreferrer"&gt;define an entity&lt;/a&gt;, simply create a class and decorate it. Here is an example of &lt;code&gt;Book&lt;/code&gt; entity defined for MongoDB driver:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see, it’s pretty simple and straightforward. Entities are simple JavaScript objects (&lt;em&gt;so called POJO&lt;/em&gt;), decorated with &lt;code&gt;@Entity&lt;/code&gt; decorator (&lt;em&gt;for TypeScript&lt;/em&gt;), or accompanied with &lt;a href="https://b4nan.github.io/mikro-orm/usage-with-js/" rel="noopener noreferrer"&gt;schema definition object&lt;/a&gt; (&lt;em&gt;for vanilla JavaScript&lt;/em&gt;). No real restrictions are made, you do not have to extend any base class, you are more than welcome to &lt;a href="https://b4nan.github.io/mikro-orm/entity-constructors/" rel="noopener noreferrer"&gt;use entity constructors&lt;/a&gt; for specifying required parameters to always keep the entity in valid state. The only requirement is to define the primary key property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfik8h6643n2l72s9v08.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfik8h6643n2l72s9v08.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might be curious about the last line with &lt;code&gt;Book&lt;/code&gt; as an interface. This is called &lt;a href="https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces" rel="noopener noreferrer"&gt;interface merging&lt;/a&gt; and it is there to let TypeScript know the entity will have some extra API methods (like &lt;code&gt;init()&lt;/code&gt; or &lt;code&gt;isInitialized()&lt;/code&gt;) available as it will be monkey-patched during discovery process. More about this can be found &lt;a href="https://b4nan.github.io/mikro-orm/defining-entities/" rel="noopener noreferrer"&gt;in the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persisting entities with EntityManager
&lt;/h2&gt;

&lt;p&gt;To save entity state to database, you need to &lt;a href="https://b4nan.github.io/mikro-orm/entity-manager/" rel="noopener noreferrer"&gt;persist it&lt;/a&gt;. Persist takes care or deciding whether to use &lt;code&gt;insert&lt;/code&gt; or &lt;code&gt;update&lt;/code&gt; and computes appropriate change-set. As a result, only changed fields will be updated in database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://b4nan.github.io/mikro-orm/" rel="noopener noreferrer"&gt;MikroORM&lt;/a&gt; comes with support for &lt;a href="https://b4nan.github.io/mikro-orm/cascading/" rel="noopener noreferrer"&gt;cascading persist and remove operations&lt;/a&gt;. Cascade persist is enabled by default, which means that by persisting an entity, all referenced entities will be automatically persisted too.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn89zawhckvxi7qm9f53d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn89zawhckvxi7qm9f53d.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching entities
&lt;/h2&gt;

&lt;p&gt;To fetch entities from database you can use &lt;code&gt;find()&lt;/code&gt; and &lt;code&gt;findOne()&lt;/code&gt; methods of &lt;code&gt;EntityManager&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;More convenient way of fetching entities from database is by using &lt;code&gt;EntityRepository&lt;/code&gt;, that carries the entity name so you do not have to pass it to every &lt;code&gt;find&lt;/code&gt; and &lt;code&gt;findOne&lt;/code&gt; calls:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Working with references
&lt;/h2&gt;

&lt;p&gt;Entity associations are mapped to entity references. Reference is an entity that has at least the identifier (&lt;em&gt;primary key&lt;/em&gt;). This reference is stored in the Identity Map so you will get the same object reference when fetching the same document from database.&lt;/p&gt;

&lt;p&gt;Thanks to this concept, MikroORM offers unified API for accessing entity references, regardless of whether the entity is initialized or not. Even if you do not populate an association, there will be its reference with primary key set. You can call &lt;code&gt;await entity.init()&lt;/code&gt; to initialize the entity. This will trigger database call and populate itself, keeping the same reference to entity object in identity map.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqldkl25qliz4mht6fwg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqldkl25qliz4mht6fwg.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Identity Map and Unit of Work
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://b4nan.github.io/mikro-orm/" rel="noopener noreferrer"&gt;MikroORM&lt;/a&gt; uses the Identity Map in background to track objects. This means that whenever you fetch entity via &lt;code&gt;EntityManager&lt;/code&gt;, MikroORM will keep a reference to it inside its &lt;code&gt;UnitOfWork&lt;/code&gt;, and will always return the same instance of it, even if you query one entity via different properties. This also means you can compare entities via strict equality operators (&lt;code&gt;===&lt;/code&gt; and &lt;code&gt;!==&lt;/code&gt;):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Another benefit of Identity Map is that this allows us to skip some database calls. When you try to load an already managed entity by its identifier, the one from Identity Map will be returned, without querying the database.&lt;/p&gt;

&lt;p&gt;The power of Unit of Work is in running all queries inside a batch and wrapped inside a transaction (&lt;em&gt;if supported by given driver&lt;/em&gt;). This approach is usually more performant as opposed to firing queries from various places.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collections
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;OneToMany&lt;/code&gt; and &lt;code&gt;ManyToMany&lt;/code&gt; collections are stored in a &lt;code&gt;Collection&lt;/code&gt; wrapper. It implements iterator so you can use &lt;code&gt;for of&lt;/code&gt; loop to iterate through it.&lt;/p&gt;

&lt;p&gt;Another way to access collection items is to use bracket syntax like when you access array items. Keep in mind that this approach will not check if the collection is initialized, while using &lt;code&gt;get&lt;/code&gt; method will throw error in this case.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;More informations about collections can be found &lt;a href="https://b4nan.github.io/mikro-orm/collections/" rel="noopener noreferrer"&gt;in the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;So you read through the whole article, got here and still not satisfied? There are more articles to come (beginning with integration manual for popular frameworks like &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; or &lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;NestJS&lt;/a&gt;), but you can take a look at some advanced features covered in docs right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/nested-populate/" rel="noopener noreferrer"&gt;Smart nested populate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/query-conditions/" rel="noopener noreferrer"&gt;Smart query conditions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/entity-helper/" rel="noopener noreferrer"&gt;Updating entity values with &lt;code&gt;IEntity.assign()&lt;/code&gt;&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/property-validation/" rel="noopener noreferrer"&gt;Property validation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/lifecycle-hooks/" rel="noopener noreferrer"&gt;Lifecycle hooks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/naming-strategy/" rel="noopener noreferrer"&gt;Naming strategy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/usage-with-nestjs/" rel="noopener noreferrer"&gt;Usage with NestJS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://b4nan.github.io/mikro-orm/usage-with-js/" rel="noopener noreferrer"&gt;Usage with JavaScript&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2j28x75z1r6aih5tab4.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2j28x75z1r6aih5tab4.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start playing with &lt;a href="https://github.com/B4nan/mikro-orm" rel="noopener noreferrer"&gt;MikroORM&lt;/a&gt;, go through &lt;a href="https://github.com/B4nan/mikro-orm#quick-start" rel="noopener noreferrer"&gt;quick start&lt;/a&gt; and &lt;a href="https://b4nan.github.io/mikro-orm/" rel="noopener noreferrer"&gt;read the docs&lt;/a&gt;. You can also take a look at &lt;a href="http://github.com/B4nan/mikro-orm-examples" rel="noopener noreferrer"&gt;example integrations with some popular frameworks&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Like&lt;/em&gt; &lt;a href="https://b4nan.github.io/mikro-orm/" rel="noopener noreferrer"&gt;&lt;em&gt;MikroORM&lt;/em&gt;&lt;/a&gt;&lt;em&gt;? ⭐️&lt;/em&gt; &lt;a href="https://github.com/B4nan/mikro-orm" rel="noopener noreferrer"&gt;&lt;em&gt;Star it&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on GitHub and share this article with your friends.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;This article was originally published on Medium: &lt;a href="https://medium.com/dailyjs/introducing-mikro-orm-typescript-data-mapper-orm-with-identity-map-9ba58d049e02" rel="noopener noreferrer"&gt;https://medium.com/dailyjs/introducing-mikro-orm-typescript-data-mapper-orm-with-identity-map-9ba58d049e02&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>node</category>
      <category>oop</category>
    </item>
  </channel>
</rss>
