Object Relational Mapping In Express
Introduction
When we write software we generally want to organize our data into objects with certain properties that describe both it and what it can do. The practice of Object Oriented Programming (or OOP) has been around for ages, and is a method generally used to accomplish this goal. It is also important to store this data in a manner so that these objects can relate to each other and so that it persists outside of our running program. The most common solution for this is SQL (structured query language). Through utilizing both of these tools we can accomplish a lot in how we manage our data. The problem is that although simple SQL queries are quite easy, once you begin trying to fetch data from Objects that relate to each other they can become quite difficult. A solution to this is a set of middleware that sits between your programs Objects and the database that performs the queries. This middleware generally falls under the category of Object Relational Mapping (ORM) software. In this article we will cover one such ORM you can use in Express.js called Sequelize.
What Is Sequelize?
Many frameworks have ORMs such as Active Record for the Ruby On Rails framework. Sequelize happens to be an ORM that can be used with Node.js frameworks such as Express to interact with databases such as Postgres, MySQL and more. In such an Express project it can be imported through npm and used to define your models, create tables within your database for said models, and configure a connection between your program and your database. If you use it to define your models it provides a few handy static methods. A few good ones to know are:
- build — allows you to instantiate an instance of a Class without saving it to the database. Use this instead of the javascript new operator.
const user = User.build({name: "John", email: "foo@bar.com"});
- create — allows you to instantiate and immediately save an instance of a Class to its corresponding table. It is important to note that this is an asynchronous method and will thus immediately return a promise to be resolved later. Because of this you generally want to use a .then statement. Or you could simply use the await operator…your choice.
const user = User.create({name: "John", email: "foo@bar.com"})
.then(user => user);
And here are a few handy instance methods you may want to know that Sequelize provides your models when you use it to define them:
- save — will add a row to the models table consisting of the attributes provided by you instantiated instance. This again is an asynchronous method and an example of needing to use .save might be to change an attribute in an instance before changing it in the database:
const user = User.create({name: "John", email: "foo@bar.com"})
.then(user => user);
user.set({email: "food@bar.com"});
await user.save();
- update — will make sure that all changes made to the instance will persist to the database. An example of using this might be:
const user = User.create({name: "Joh", email: "fo@bar.com"})
.then(user => user);
user.name = "John";
await user.update({email: "foo@bar.com"});
await user.save();
- destroy — will remove an instance from the database. An example of using this to delete something would be:
const user = User.create({name: "Joh", email: "fo@bar.com"})
.then(user => user);
await user.destroy();
Feel free to read more amazing static and instance methods Sequelize can provide you in the docs.
Implementing Sequelize Within Express.js
In order to better understand how an ORM like Sequelize can be useful lets implement it in a demo Express application. This application will follow and MVC pattern and will allow users to create both Owners and Pets. We will use MySQL as our Relational Database Management System (RDMS). The next step is to setup a MySQL database. If you previously read my article on how to setup a MySQL database for an Express application this should seem familiar to you. This process will follow the same process as the ‘Creating Our Database’ section except during the last step you will not be creating tables through the MySQL command line client. In short the process for creating your MySQL database for this application should resemble this:
Now that we have created our database go ahead and create your project folder where ever you’d like. After navigating to it and opening your text editor (I use VS Code) you’ll want to open a terminal again inside your project. The first step we’re going to do is initialize node by entering npm init inside terminal. After the appearance of your package.json file you’ll want to install some packages as dependencies using the following format:
npm i --save package_name
You should do this for the following packages:
After doing this your package.json file should look something like this:
Also you’ll want to setup the following file structure (This also includes a README.md and a package.json but they were cut out for this screen shot):
One thing to keep in mind is that databases generally require passwords…but you should never store your password in any file you are going to push to a repository. To accomplish this first create a .gitignore file and specify the .env file you’ll store your password in. Also specify the node_modules folder so that you can keep your repository slim and that neither of these will ever be pushed to any repository. Once this is complete create a .env file that you will store your database password in under a global variable. Once this is complete we will head over to our database setup within util/database.js. Within this file we’re going to want to create a sequelize instance by importing our sequelize package and using it to configure our database connection. We will also want to import our dotenv package in order to use our global variable containing our databases password within the sequelize instances configuration. Once this is complete your util/database.js file should look something like this:
Now that we have this setup lets focus on the M of our MVC pattern. That is of course the models. We are going to need one for our Owners and one for our Pets. Both of these will need to import our sequelize package and our sequelize instance with our database connection configuration we just made. We will then use the define method our imported sequelize instance provides us to describe our model and setup corresponding tables within our database. If we did this for our Owners model our models/owner.js would look something like this:
When this is completed we can focus on the C in MVC and that is the Controllers. These will contain all of the logic for creating owners and pets. If we continue focusing on Owners we would head to controllers/owner.js. In this we would import our new Owner class. In order to create and read owners we will need to make use of some of the previously mentioned methods sequelize provides us. Specifically we will be using create to both create and save an Owner instance, and findAll to provide us with an array of all Owner instances. After we define our middleware for our different controller actions where we implement these methods, our controllers/owner.js file should look something like:
If you are interested in what the Views would look like for an app like this I encourage you to checkout the demo repository I’ve set up for this example on GitHub. Once we have completed our controller actions we should head over to define the routes that will implement this middleware. If we were to continue focusing on our Owners we would head over to routes/owner.js. Within this file we will first want to import express in order to create our router object through express.Router(). After we do this we use this router object to define the paths for our routes by using route methods which are derived from HTTP methods. Once t his is done our routes/owner.js would look something like this:
Once this is completed we can pull it all together within the entry point of our project which is app.js. In this file you will import everything we just worked on along with setting up whatever model associations you feel necessary through sequelize. Once this is all set up at the end of this file you’re going to want to tell sequelize to communicate with your database. This will set up associated tables for models if they don’t already exist and will execute asynchronously. Do this by calling sequelize.sync(). There are a few options that dictate how sequelize interacts with your database and I encourage you to follow that link to see a few of them. After this you’re going to want to add a .then statement and start your server on the appropriate port. Doing all of t his will make app.js look something like this:
After this you should have a working application!
Conclusion
By using Sequelize we are able to query our database for our related objects with ease within our Express projects. If you are curious feel free to browse a repository on GitHub I have set up that demonstrates how to utilize Sequelize within in Express project. I hope this has shed some light on just how useful ORMs are and of course what they are. Until next time happy coding!