DEV Community

Cover image for ORM Database Fundamentals
Fabrizio Lallo
Fabrizio Lallo

Posted on

ORM Database Fundamentals

Table of Contents

  1. What is an ORM Database?
  2. Query Builder
  3. Identity Map
  4. Unit of Work
  5. Conclusion

What is an ORM Database?

An ORM Database (Object Relational Mapping) is concerned with helping your application achieve persistence. Persistence simply means we would like our application’s data to outlive the application process. But, expressly, Object Relational Mapping is a technique to achieve a mapping between database data and objects used with your programming language.

Object Relational Mapping achieves this goal through fundamental concepts:

  • Query Builder
  • Identity Map
  • Unit of Work

Query Builder

A Query Builder provides an API designed for constructing a DQL (Domain Query Language) query in several steps. It provides a set of classes and methods that can build queries programmatically. Usually, you can use Query Builder API to build a query quickly or just use the raw DQL language if you need something more complex that it’s easy to write in raw DQL language.

So let’s imagine we need to execute the following SELECT query in our application:

SELECT * FROM Users
WHERE name='John';
Enter fullscreen mode Exit fullscreen mode

A Query Builder API to select rows in a table could be:

orm.select('*')
  .where({
    name: 'John',
  })
Enter fullscreen mode Exit fullscreen mode

Most of the time, people think this is the definition of ORM, but as we’ll see, two other fundamental concepts are essential for an ORM to be defined as such.

Identity Map

An Identity Map keeps a record of all objects that have been read from the database in a single business transaction. Whenever you want an object, the ORM checks the Identity Map first to see if that object is already contained. So, it acts as a cache.

Having an identity map is crucial for avoiding cases when you read the same database record in two different objects. In this case, when you update them both, you'll have a lousy time writing the changes out to the database correctly.

Furthermore, reading the same record several times can cause an expensive cost in remote calls to the database. So, not loading the same data twice helps avoid profound problems writing changes to the database and speeds up your application.

Let’s put it into practice with some javascript code:

// Both queries return the same user
const user1 = orm.select('*')
  .where({
    name: 'John',
      surname: 'Doe'
  })

const user2 = orm.select('*')
  .where({
    name: 'John',
      surname: 'Doe',
    age: 27
  })

// identity map in action
console.log(user1 === user2) // true
Enter fullscreen mode Exit fullscreen mode

Unit of Work

A Unit of Work keeps track of every change you make during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database due to your work.

Keeping track of what you've changed when pulling data in and out of a database is fundamental. Otherwise, that data won't be written back into the database.

You can change the database with each change to your object model, but this can lead to many very slow and very small database calls. Furthermore, it requires you to have a transaction open for the whole interaction, which is impractical if you have a business transaction that spans multiple requests.

Let’s see what a unit of work looks like:

const user1 = orm.select('*')
  .where({
    name: 'John',
      surname: 'Doe',
    age: 27
  })

user1.age = 30;

const user2 = orm.select('*')
  .where({
    name: 'Jane',
      surname: 'Doe',
    age: 25
  })

user2.age = 32;

// it will apply all the changes done in this unit of work
// so user1 and user2 age will be updated in the database
// using a single transaction
orm.flush(); 
Enter fullscreen mode Exit fullscreen mode

Usually, when there are a lot of changes, an ORM should take care to batch the changes in several transactions in order not to create a single heavy transaction.

Conclusion

In this blog post, we explored the fundamental concepts of a Database ORM: Query Builder, Identity Map and Unit of work.

Certainly, an ORM has many features to make easy interaction with a database, but these are the main building blocks.

Stay tuned for the next blog posts. 👀

Follow me on Twitter if you enjoyed this blog post @fabri.lallo

Top comments (0)