An Intro to Object-Relational Mapping With TypeORM in Node.js
Object-Relational Mapping (ORM) is a technique that lets one access and modify data from a database using an object-oriented paradigm. In this lesson, we'll discuss ORM and be introduced to a popular ORM used for JavaScript and TypeScript, TypeORM.
TypeORM#
What is ORM?#
In our previous lesson, we wrote SQL statements like the following to perform CRUD operations on our PostgreSQL database:
INSERT INTO public.test_users(id, name) VALUES ('001', 'bob');
SELECT * FROM public.test_users WHERE id='001';
UPDATE public.test_users SET name='bob_name_updated' WHERE id='001';
DELETE FROM public.test_users WHERE id='001';
SQL statements like the above are the most basic and simple statements that are often taught to new developers. Depending on what you want to achieve and the complexity of your database, SQL statements can become extremely complex. Some SQL statements can be hundreds of lines of code and many companies have dedicated SQL developers!
Object-Relational Mapping (ORM) is a technique that lets you access and modify data from a database using an object-oriented paradigm. In other words, instead of writing SQL statements manually, we can use a library to generate these SQL statements using some "virtual database object". For example, to perform the same CRUD operations on our PostgreSQL database as the above while using an ORM, our code could look something like the following:
// INSERT INTO public.test_users(id, name) VALUES ('001', 'bob');
const user = await db.users.create({ id: "001", name: "bob" }).save();
// SELECT * FROM public.test_users WHERE id='001';
const user = await db.listings.findOne({ id: "001" });
// UPDATE public.test_users SET name='bob_name_updated' WHERE id='001';
const user = await db.users.findOne({ id: "001" });
user.name = "bob_name_updated";
await user.save();
// DELETE FROM public.test_users WHERE id='001';
const user = await db.users.findOne({ id: "001" });
await user.remove();
As we can see, an ORM can abstract away our SQL implementation. With that said, there are some advantages and disadvantages of using an ORM.
Pros of ORM 👍#
We can write in the language of our choice. For us, this will be TypeScript.
It abstracts away the database so switching from MongoDB to PostgreSQL (as an example) is extremely easy.
Many ORMs support advanced features such as database migrations.
Unless you're a master at SQL, statements generated by an ORM will most likely perform better than the ones you write yourself.
Cons of ORM 👎#
An ORM must be configured before usage.
By abstracting away the database, many new developers won't understand what's happening under the hood.
TypeORM#
The ORM we'll be using for this course is TypeORM. TypeORM is an extremely popular ORM that supports multiple database systems such as MySQL, PostgreSQL, MongoDB, and more. It also integrates extremely well with TypeScript.
Before we start to integrate TypeORM into our TinyHouse application, let's spend some time getting familiar with TypeORM's API using a simple Node server. To begin, we'll clone the source code from lesson 4.9 in Part I of the course.
Install & Update#
First, we'll make sure our npm packages are installed:
npm install
Next, we'll make sure our npm packages are updated:
npm update
If npm warns about any vulnerabilities from our packages, we'll also want to make sure we fix those:
npm audit fix
Since we'll be using TypeORM and PostgreSQL instead of MongoDB, we'll uninstall the MongoDB driver and the accompanying type definitions file:
npm uninstall mongodb --save
npm uninstall @types/mongodb --save-dev
To integrate TypeORM into our Node server, we'll simply follow the instruction found on their official documentation. First, we'll install the packages that TypeORM requires:
npm install typeorm reflect-metadata
Next, we'll install the PostgreSQL database driver:
npm install pg
Next, we'll enable the following settings in our tsconfig.json
:
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
Config#
In our server project, we'll create a new .env
file with a PORT
variable set to 9000
:
PORT=9000
Remember that when we were using MongoDB, we had to setup DB_USER
, DB_USER_PASSWORD
, and DB_CLUSTER
values in our .env
file to specify the configuration variables we'll need to connect to our database? TypeORM on the other hand, uses an ormconfig.json
file to store these variables. We'll head over to their official quick start guide to get a copy of this file and place it in the root of our server project.
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "test",
"password": "test",
"database": "test",
"synchronize": true,
"logging": false,
"entities": ["src/entity/**/*.ts"],
"migrations": ["src/migration/**/*.ts"],
"subscribers": ["src/subscriber/**/*.ts"]
}
This page is a preview of TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two