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.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two with a single-time purchase.
[00:00 - 00:13] From our previous lesson, we learned to write SQL statements like these to perform CRUD operations on our Postgres database. These SQL statements are the most basic and simple statements taught to new developers.
[00:14 - 00:27] 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.
[00:28 - 00:47] Object Relational Mapping or 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're going to use some library to generate the SQL statements using some virtual database object.
[00:48 - 01:00] For example, to perform the same CRUD operations on our Postgres database, using an ORM, our code could look something like this. As you can see, this completely abstracts away our SQL database.
[01:01 - 01:05] Here are some pros and cons of ORM. Pros of ORM.
[01:06 - 01:16] Writing in the language of your choice. For us, this will be TypeScript. Abstracts away the database, so switching between MongoDB and Postgres is extremely easy.
[01:17 - 01:28] Many ORM support advanced features such as database migrations. Unless you are a master at SQL, statements generated by an ORM will most likely perform better than the ones you write yourself.
[01:29 - 01:34] Cons of ORM. An ORM must be configured before usage.
[01:35 - 01:45] By abstracting the way the database, many new developers will not understand what is happening under the hood. The ORM we'll be using for this course is TypeORM.
[01:46 - 01:55] TypeORM is an extremely popular ORM that supports multiple database systems. Such as MySQL, Postgres, MongoDB and much more.
[01:56 - 02:11] It also integrates extremely well with TypeScript. Before we start integrating TypeORM into our tiny house application, let's spend some time getting familiar with TypeORM's API using a simple node server.
[02:12 - 02:24] To begin, clone the source code from Lesson 4.9 from part 1 of the course. First, we'll make sure our npm packages are installed using npm install.
[02:25 - 02:57] Next, we'll make sure our npm packages are updated using npm update. If npm warns about any vulnerabilities from our packages, we'll also want to make sure we fix those using npm audit fix.
[02:58 - 03:25] Since we'll be using TypeORM and Postgres instead of MongoDB, we'll be uninst alling the MongoDB drivers. To integrate TypeORM into our node server, we'll simply follow the instructions found on their official documentation.
[03:26 - 03:46] First, we'll install the packages TypeORM requires by running npm install Type ORM and reflect metadata. Next, we'll install the Postgres database driver by running npm install Pg.
[03:47 - 03:59] Next, we'll enable the following settings in TS config. First, we'll create a new .env file with a port variable set to 9000.
[04:00 - 04:13] Remember, when we were using MongoDB, we had to set up dbuser, dbuser password, and db cluster in our .env file as well. TypeORM on the other hand, uses an ORM config.json file to store these variables.
[04:14 - 04:25] Let's head over to their official Quick Start guide to get a copy of this file. Now we'll make the following modifications.
[04:26 - 04:31] Change Type to Postgres. Change Port to the port your Postgres server runs on.
[04:32 - 04:36] For me, this is 5432. Change username to the Postgres super user.
[04:37 - 04:42] For me, this is simply Postgres. Change password to your Postgres super user's password.
[04:43 - 04:48] For me, this is my password. Change database to the Postgres database you wish to connect to.
[04:49 - 04:54] For me, I will use the same database from the previous lesson. Test db001.
[04:55 - 05:03] We'll leave Synchronize to True. This tells TypeORM to update the schema in our Postgres server automatically when we update the schema in our source code.
[05:04 - 05:12] We'll leave Logging to False. However, if you want to see the SQL statements generated by TypeORM in your console, you can turn this option to True.
[05:13 - 05:27] Finally, we'll update the path to entities, migrations, and subscribers. By updating the variables in this ORM config.json file, TypeORM can be configured to connect to other databases, such as MongoDB or MySQL.
[05:28 - 06:00] According to TypeORM's installation instruction, we'll first need to import Reflect metadata in the beginning of our code. Next, we'll head over to our database folder and modify our Connect database function to use TypeORM's CreateConnection method, which basically takes the information from our ORM config.json file to connect our node server to our Postgres database.
[06:01 - 06:27] Next, we'll create a new folder called Entity. Because TypeORM is designed to support multiple database systems, such as Postgres and MongoDB, the term Entity is used to represent a SQL table or a MongoDB collection. This Entity folder is where we'll define our database schema.
[06:28 - 07:20] In this folder, we'll create and export a listing entity, and we'll create a new folder called Entity. Entity is used to specify the name of our SQL table.
[07:21 - 07:36] Primary column ensures a column must contain unique values, which can be used to identify each row of data. Here, we are introduced to some new data types.
[07:37 - 07:53] Text represents a string. We learned about this in the previous lesson. Varchar, also known as Character Varying, also represents a string. However, we can set a maximum length to this data type.
[07:54 - 09:14] To remove the node initializer TypeScript error, we'll disable the following setting in TS config. Integer represents an integer number.
[09:15 - 09:39] Decimal represents a decimal or floating point number. To see a full list of data types type ORM supports for each database system head over to their official documentation.
[09:40 - 10:10] Let's head back to our connect database function to import the new listing entity and export a database object. Next, we'll need to modify our TypeScript definitions like so.
[10:11 - 10:25] Instead of using MongoDB's collection type, we'll use TypeORM's repository type . Instead of using MongoDB's underscore ID of TypeObject ID, we'll use ID of Type String.
[10:26 - 10:50] To explore TypeORM's API a bit more, let's head over to our GraphQL type-def file and make the following changes. We'll add a new listing query which we'll find one listing based on user input.
[10:51 - 11:05] We'll add a new create listing mutation which we'll insert a new listing into our database. We'll add a new update listing mutation which we'll find and update one listing based on the user's input.
[11:06 - 11:17] We'll also need to change listing ID from type ID to optional ID. This is because TypeORM's delete1 method returns a deleted object without the ID.
[11:18 - 11:33] Before we start modifying our GraphQL resolvers to use TypeORM instead of Mongo DB, let's see our Postgres database with some data. In the previous lesson, we learned how to manually insert data into a Postgres database using the insert SQL statement.
[11:34 - 11:42] Now we'll do the same from our source code. Instead of using MongoDB's object ID method, we'll use node crypto library instead.
[11:43 - 12:34] [silence] Let's run our seed function by running npm run seed. [silence] And we can see our seeded data in our test listings table from the PGR admin application.
[12:35 - 12:53] Finally, let's modify our GraphQL resolvers to use TypeORM. [silence] Let's start off simple and find one listing from our test listings table.
[12:54 - 13:29] [silence] We'll use TypeORM's find1 method. [silence] Next, to find all the listings in our test listings table, we'll use TypeORM's find() method.
[13:30 - 13:56] [silence] Next, to insert a new listing into our test listing table, we'll use TypeORM's create() method to create a new instance of an entity local name. And then we'll use the save() method to save it to our database.
[13:57 - 14:45] [silence] Next, to update a database in our test listings table, we'll use TypeORM's save () method to save any entity changes to our database. [silence] And finally, to delete a listing from our test listings table, we'll use TypeOR M's remove() method.
[14:46 - 14:58] To see a full list of TypeORM's repository API, check out their official documentation. Finally, we can start our node server and test out our GraphQL API by running npm start.
[14:59 - 15:16] In the GraphQL playground, we can find all the listings using the listings query. [silence] Find one listing using the listing query.
[15:17 - 15:32] Create a new listing using the create listing mutation. [silence] Update a listing using the update listing mutation.
[15:33 - 16:01] [silence] Delete a listing using the delete listing mutation. Now that we have gotten familiar with TypeORM's API, in the next lesson, we'll integrate Postgres and TypeORM into our tiny house application.