Diving (a little) Into The JavaScript ORM Rabbit Hole

Image for post
Image for post

The journey of a developer, like any other professional minimally devoted to learning continuously, inevitably has a continuous learning factor. In my case, this learning curve has been intense and full of weekly novelties. The hot topic of the week has been something that changed completely my view on code and database organization. We are speaking of ORMs or Object-Relational Mapping.

ORM is a computer-science technique for converting data between incompatible data systems, or, in the most common case, querying and manipulating data from a database, by using object-oriented languages. In other words, an ORM works as a “translator” between such systems. Taking the SQL paradigm as an example, it’s translating a database query such as this:

SELECT * FROM students WHERE name = 'James';

To this (using JavaScript as an example):

const { myOrm } = require('my-orm-library');const student = myOrm('students').where({ name: 'James' });

Long story short, you create and manage your database from objects in your favorite programming language. Instead of querying to create the database and then carrying the data to your code, the ORM does the entire thing from the beginning!

A basic ORM (Object Related Mapping) schematic.
A basic ORM (Object Related Mapping) schematic.
How an ORM does the mapping (or translation) of an object to data in a relational database.

This leads to the main feature of any ORM: the Model-View-Controller pattern, or MVC.

And what does the MVC do? It encapsulates a software’s development logic into three intertwined elements, each responsible for its role in an application:

  • The Model contains the application data, logic, and basic rules of the application.
  • View outputs the visual representation of the model in some form.
  • Lastly, the Controller manages the interaction and validation between user inputs from the View, performing interactions in the data model objects.

In some ORMs, like Ruby’s Rails-based Active Record, the validation and basic rule logic are also managed by the Controller, while the Model takes care of the data modeling and manipulation.

A basic diagram of an MVC pattern functioning in an ORM would look like this:

Model-View-Controller basic schematic
Model-View-Controller basic schematic
Active Record’s MVC pattern managing the interaction between browser, user, and database.

My current (and ongoing, as of September 2020) experience with ORM is Active Record, Ruby’s most popular development library. At the same time that it helped me understand much better object-oriented programming and provided a much cleaner code style, it’s been learning to ride a bike again from scratch. The basic drawback of any ORM is that it acts as a translator, and because of that, speaking in development terms, it’s almost like learning a new programming language entirely. It does compartmentalize and organize your logic in a much better way, but requires a new learning curve, since it is kind of a dialect in the programming language you are working on, and the MVC pattern may not be very familiar for the code newbie — myself included.

These are some advantages of using an ORM:

  • You may keep writing in the same programming language you are used to and don’t need to take long learning proper SQL statements to build and manipulate your databases.
  • Since it uses your programming language to abstract database querying, you may switch database systems, as long as both systems are supported by the ORM library.
  • Many ORMs include other advanced features out of the box, such as progressive database migrations (meaning easier database manipulation), seeding, and transactions, among other features. Such features help prevent SQL injections, as well.
  • Most ORMs automate the data modeling process, taking fewer steps from the developer to organize the code inside their projects.
  • Since the cornerstone of an ORM is writing code in the MVC pattern, your code gets cleaner and more reusable.

Bear in mind, however, that adopting an ORM isn’t unanimity among programmers. When I first Googled the subject, I quickly found a lengthy criticism against ORMs, demonstrated with practical JavaScript examples. Some of the advantages described include:

  • For the same reason, you stick to your current programming language, using an ORM leads you to not learn appropriately how SQL is programmed and structured, leading to technical deficiencies.
  • ORMs are usually efficient for querying simpler database structures, but that isn’t the case when you need to develop more complex queries. Since the ORM created a new abstraction layer with the object model, this comes with a toll on performance. This article gives a SQL vs. ORM performance comparison to demonstrate such reality, and this repository demonstrates the same issue within Node ORM libraries.
  • Despite adopting the programming language you are working on, ORMs still bring a new layer to learn, since they come with their patterns, setups, special syntax, and features. This may be particularly time-consuming or confusing for new developers.
  • ORM database building is still an automated process. If you have solid SQL knowledge, you probably may build better performing queries by yourself.

All things said and described regarding ORMs and what they may bring, I have decided to explore a little more on the topic with JavaScript ORM libraries, since JS is the first programming language I have learned as a web developer, and this means I will inevitably bump into projects and systems that adopt such libraries. I am taking some time to describe a little about three of the most popular ORM libraries available and what they may bring to developers.

Before I go on, I’m only opening a brief parenthesis on how I sorted these libraries first:

  • Despite its great popularity, Knex is NOT an ORM. Knex is a SQL query builder that, despite supporting many databases such as Postgres, MySQL, MariaDB, and many others, does not perform Object Related Mapping. That role is still up to the developer, on their own or by utilizing an ORM. By the way, one of the ORMs I’ll present uses Knex as their query builder.
  • I have prioritized ORMs that support multiple databases since one of the essential points of adopting such a library is avoiding the hassle of restructuring your entire query building in the event of a database system migration.

1. Sequelize

Sequelize Logo
Sequelize Logo
Sequelize, the most popular JavaScript ORM library available.

Sequelize is by far the most popular JavaScript ORM library, with over 700,000 weekly downloads, and has been maintained and updated for almost ten years. The constant and consistent response to issues justifies its enormous popularity, making it considered a solid ORM library for JavaScript.

Sequelize supports Postgres, MySQL, MariaDB, SQLite, and Microsoft SQL Server. Being Promise-based, it helps many developers who are used to use this object model quickly getting acquainted with their library. Other features that Sequelize include are, but not limited to:

  • Database synchronization
  • Database migrations
  • Model validations and hooks
  • Data seeding, relations, and even raw queries to the developer’s taste
  • Facilitated testing

Sequelize features extremely rich and detailed documentation, separated by version to help out legacy development, and includes an API reference. Their documentation may be hard to read sometimes, though.

If you value development stability, you probably want to stick with Sequelize as your JavaScript ORM of choice.

2. TypeORM

TypeORM Logo
TypeORM Logo
TypeORM, the most popular ORM of choice for TypeScript developers.

TypeORM is a relatively new library, compared to other ORM counterparts, having its first release four years ago. Nonetheless, its compatibility with both TypeScript and modern JavaScript (ES5 onwards) made it increasingly popular among developers, by having almost half the weekly downloads as its most popular and usual counterpart, described above.

Looking at TypeORM’s documentation almost felt like looking at a Saturday morning ad, since it enjoys boasting a wide array of features and compatibilities. Here’s part of such list, from their landing documentation page:

  • DataMapper or Active Record pattern support
  • Connection configuration in JSON, XML, YML and ENV formats
  • Connection pooling
  • Entity management
  • Multiple database connections
  • Support for many frameworks, browsers, and platforms such as React Native
  • Support to a wide array of database systems, including MongoDB, which is a NoSQL (non-relational) database, something which most ORMs do not support

As you travel through their documentation, you quickly get tempted to throw all other options under the bus and immediately adopt TypeORM as your ORM library of choice. However, after some research, I quickly realized that my feeling that I was looking at a Saturday ad wasn’t flawed, after all. A recent comparison between TypeORM and Sequelize points out two jarring problems in TypeORM: poorly detailed documentation (despite their excellent presentation), and lack of native data seeding. While Sequelize supports native data seeding, TypeORM requires an external plugin to do so, extending dependency requirements and potentially generating side effects for testing.

Though it seems to be the ideal ORM of choice for TypeScript developers, many pros tend to advise caution when using TypeORM.

3. Bookshelf

Bookshelf.js Logo
Bookshelf.js Logo
Bookshelf, an ORM that supports callback-based modeling.

Bookshelf is a distant third option for developers, featuring close to 100,000 weekly downloads. It’s a Node.js built on the Knex SQL builder and supports the Postgres, MySQL, and SQLite SQL databases. What makes Bookshelf stand out compared to the other two mentioned libraries is their support to callbacks, becoming a potential choice for developers who favor functional programming over Sequelize promise-based modeling (also supported by Bookshelf) or TypeORM’s class-based modeling.

Other features present in Bookshelf are:

  • Support to the most common SQL relations (one-to-one, one-to-many, many-to-many)
  • Polymorphic associations
  • Eager (nested of not) relation loading

Bookshelf seems to be a simpler library compared to TypeORM or Sequelize, but their support to callbacks may stand out to some developers, so it’s always nice to present a different choice to work with.

Okay, but what about YOU, Joao?

Which JavaScript ORM rabbit hole are you diving in, anyway?

Thinking…
Thinking…
That’s a lot of food for thought…

I will probably look at this post (my first development-related post ever, by the way) in a couple of years and take a peal of good laughter, or at least reflect deeply after reading this last section. As I stated at the beginning of this article, as a new developer, I feel like a kid in their 10-year birthday party getting all the cool toys every ten minutes. Incredibly amazed by the next toy I get to play, even if I don’t fully understand yet how it works. I enjoy it because it’s cool to play with, only to be amazed by the next toy available. It has been my life as a developer in a nutshell for the last three months. This may be awesome most of the time but perhaps overwhelming sometimes. It has been the case in this new world of Object-Related Mapping, and the Model-View-Controller pattern that ensues.

I have also quickly figured out that ORMs are a more controversial and opinionated topic than I had expected. Though many developers value it as a tool to simplify their code style and development, many other developers see ORMs as a remedy that might do more harm to the patient (in this case, the database model and structure) than good. Being a new developer, such general insight honestly surprised me.

I also tend to value stability and community support when dealing with programming languages, libraries, and tools. After exploring these three JavaScript ORM documentation and researching over the developer community perception, experience, and comparisons, my ORM of choice will definitely be Sequelize, despite being more verbose than the other two competitors. It will take me some time to get comfortable with using (and mastering!) its use, and the MVC pattern in general within JavaScript (I am getting to know it with Active Record and Rails), but learning is always a continuous process, and doing so as a developer isn’t an exception.

If you wish to get to know better about ORM and its corresponding JavaScript libraries, I suggest some links I have navigated to better know the topic:

Written by

Business Analyst shifted to Web Development. Also, a fighting games enthusiast.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store