Popular ORMs (Object-relational Mapping) in JavaScript
As software developers, we are always trying to find a better approach to optimize our code and keep it DRY for the best performance of the program. While there are many coding principles to keep your code clean, ORM is one of the most popular ways to optimize your code.
Why is that you asked? Because we can get rid of all the SQL code from the code base by using ORM!
What is ORM?
So, what is ORM? According to WIKIPEDIA, this is the definition of ORM:
Object–relational mapping (ORM, O/RM, and O/R mapping tool) in computer science is a programming technique for converting data between a relational database and the heap of an object-oriented programming language. This creates, in effect, a virtual object database that can be used from within the programming language.
What does it really mean? In your program, you normally would need to write a query to retrieve the data from the database. So do we need to learn SQL to be able to write all CRUD operation queries? Well, no if you decide to use an ORM for your system.
Object Relational Mapping (ORM) is a technique for converting a database query result into entity class instances. An entity is simply an object wrapper for a database table. It contains attributes that are mapped to columns of a database table. Entity instances have ways of performing CRUD operations and have support for additional functions that contain custom logic such as validation and data encryption.
For example, if you have a book class that you want to retrieve all the books of which the author is “Linus”. Manually, you would do something like:
book_list = new List();
sql = "SELECT book FROM library WHERE author = 'Linus'";
data = query(sql); // I over simplify ...
while (row = data.next())
{
book = new Book();
book.setAuthor(row.get('author');
book_list.add(book);
}
With an ORM library, it would look like this:
book_list = BookTable.query(author="Linus");
The mechanical part is taken care of automatically via the ORM library.
What is ORM Library?
When talking about ORM, most people are referring to a library that implements the Object-Relational Mapping technique, hence the phrase “an ORM”.
An ORM library is an object-relational mapper that encapsulates the code need to manipulate the data and carries out the work of object-relational mapping for us, so we don’t need to use SQL anymore.
It can be written in the language of our choice; which allows us to interact directly with an object in the same language as our program.
Popular ORMs in Javascript
When there are many ORM libraries available for multiple different languages, this article will focus on popular libraries for Javascript.
Objection.js
- Website
- Documentation
- Compatible Database Systems: SQLite3, Postgres, and MySQL (including all Knex.js supported databases)
Objection.js is a minimal Node.JS ORM, launched in April 2015, that is designed to stay out of your way and make it as easy as possible to use the full power of SQL and the underlying database engine. Built on the query builder Knex, Objection supports all databases supported by Knex.
Objection provides an easy declarative way of defining models and relationships between them. One of the objection’s main features is powerful, mechanisms for eager loading, inserting, and upserting object graphs. It also has official built-in support for TypeScript.
Objection is an open-source project with over one hundred thousand weekly downloads. Even though ORM is the best commonly known acronym to describe objection, a more accurate description is to call it a relational query builder. You get all the benefits of an SQL query builder but also a powerful set of tools for working with relations.
Simple queries
Simplified examples of common database operations
//Finding all
Model.query();
//Create
Model.query().insert(
{
firstName: "Britney",
lastName: "Spears",
email: "britney@pop.com"
});
//Passing where clauses to a find operation
Model.query().where({ id: 1});
//Find specific columns from the table
Model.query().select('id', 'lastName')
//Update
Model.query()
.findById(1)
.patch({ lastName: 'Jeans' });
//Delete
Model.query().deleteById(1);
Prisma
- Website
- Documentation
- Compatible Database Systems: Postgres, MySQL, MariaDB, SQLite, AWS Aurora, Microsoft SQL Server, Azure SQL, MongoDB, and CockroachDB
Prisma is a next-generation ORM, launched in April 2019, that makes it easy for developers to reason about their database queries by providing a clean and type-safe API for submitting database queries that return plain old JavaScript objects. It provides the following tools:
- Prisma Client — a client library that provides a type-safe query builder for Node.js & TypeScript
- Prisma Migrate — a migration system that autogenerates when changes are made to the schema file
- Prisma Studio — a modern GUI to view and manage data in the database
Prisma Client can be used in any Node.js (supported versions) or TypeScript backend application (including serverless applications and microservices). This can be a REST API, a GraphQL API, a gRPC API, or anything else that needs a database. Centered around a GraphQL-like DSL schema, Prisma lets you cleanly define your database structure.
Prisma is an open-source Node.js and TypeScript ORM with half of a million weekly downloads. Prisma Studio GUI is the only part of Prisma ORM that is not open source as it can only run locally.
Simple queries
Simplified examples are taken from https://sequelize.org/master/manual/model-querying-basics.html
//Finding all
prisma.model.findMany()
//Create
prisma.model.create({
data: {
id: 4,
firstName: 'Britney',
lastName: 'Spears',
email: 'britney@pop.com',
},
});
//Passing where clauses to a find operation
prisma.model.findUnique({
where: { id: 1 }
});
//Find specific columns from the table
prisma.model.findMany({
select: {
id: true,
lastName: true,
},
});
//Update
prisma.model.update({
where: { id: 1 },
data: {
lastName: 'Jeans',
},
});
//Delete
prisma.model.delete({
where: { id: 1 }
});
Sequelize
- Website
- Documentation
- Compatible Database Systems: Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Oracle Database, Amazon Redshift, and Snowflake’s Data Cloud
Sequelize is a well-known easy-to-use and promise-based Node.js Object Relational Mapper, launched in Jul 2010, that makes it easy to work with multiple database management systems. (Being a promise-based ORM means that it supports Node.js promises). Sequelize’s powerful migration mechanism can transform existing database schemas into new versions. Overall, Sequelize provides excellent support for database synchronization, eager loading, associations, transactions, and database migrations while reducing development time and preventing SQL injections.
Sequelize is an open-source ORM with millions of weekly downloads. It supports raw SQL statements, which gives developers the flexibility to write complex and highly performant SQL statements. Sequelize also supports migrations and has a CLI tool for generating and seeding data.
Simple queries
Simplified examples are taken from https://sequelize.org/master/manual/model-querying-basics.html
//Finding all
Model.findAndCountAll({});
Create:
Model.create(
{
id: 4,
firstName: "Britney",
lastName: "Spears",
email: "britney@pop.com"
});
//Passing where clauses to a find operation
Model.findAll({
where: {
id: { [Op.eq]: 1 },
},
});
//Find specific columns from the table
Model.findAll({
attributes: ["id", "lastName"],
});
//Update
Model.update(
{ lastName: 'Jeans' },
{ where: { id: 1 } }
);
//Delete
Model.destroy({
where: { id: 1 }
});
Conclusion
Objection, Prisma, and Sequelize are all great ORM options with robust features but this is just a selection of some of the very useful libraries among many others.
Aside from the many benefits of ORM that were explained above, one of the most beneficial reasons for using ORM is having documentation of the data layer of the project without having to do it yourself. Using well documented ORM library makes it easier to maintain the database system of the project in the long run.
As we conclude, I’d like to briefly discuss some disadvantages of using ORM libraries in your project. The main arguments include:
- bulky, inefficient queries
- learning curve of ORM libraries and frustrations using it
- migration issues: keeping entity classes and the database scheme in sync
- loss of type safety when using the raw SQL option
There are some articles to read all the arguments against using ORM libraries here and here.
Most of the arguments against ORM libraries have been resolved by the newer ones, such as Object.js and Prisma. If you decide not to use an ORM library, you’ll have to decide on the individual tools and libraries that make up your data layer stack.
Now that you know what ORMs are, their features, and their drawbacks, you can decide if you want to spend some time learning about ORMs in-depth and add it to your project or stick to the original way of embedding SQL code in your project.