Introduction to MikroORM with PostgreSQL
So far, in this series, we’ve used a few different solutions for managing databases. To work with MongoDB, we’ve used Mongoose. To manage a PostgreSQL…
So far, in this series, we’ve used a few different solutions for managing databases. To work with MongoDB, we’ve used Mongoose. To manage a PostgreSQL database, we’ve utilized TypeORM and Prisma. This article looks into another Object-relational mapping (ORM) library called MikroORM. By having a broad perspective on what’s available, we can choose the library that fits our needs the most. You can find all of the code from this article in this repository. Setting up MikroORM and PostgreSQL The most straightforward way to use PostgreSQL in our project is to use Docker. In the second part of this series, we set up PostgreSQL and TypeORM. Therefore, we can use the same docker-compose.yml file we created back then. docker-compose.yml version: "3" services: postgres: container_name: nestjs-postgres image: postgres:latest ports: - "5432:5432" volumes: - /data/postgres:/data/postgres env_file: - docker.env networks: - postgres pgadmin: links: - postgres:postgres container_name: nestjs-pgadmin image: dpage/pgadmin4 ports: - "8080:80" volumes: - /data/pgadmin:/root/.pgadmin env_file: - docker.env networks: - postgres networks: postgres: driver: bridgeAlso, we need to create a file that contains the variables our docker container needs. docker.env POSTGRES_USER=admin POSTGRES_PASSWORD=admin POSTGRES_DB=nestjs PGADMIN_DEFAULT_EMAIL=admin@admin.com PGADMIN_DEFAULT_PASSWORD=admin Connecting to the database To be able to connect to the database, we need to establish a set of environment variables our NestJS application will use. app.module.ts import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import * as Joi from 'joi'; @Module({ imports: [ ConfigModule.forRoot({ validationSchema: Joi.object({ POSTGRES_HOST: Joi.string().required(), POSTGRES_PORT: Joi.number().required(), POSTGRES_USER: Joi.string().required(), POSTGRES_PASSWORD: Joi.string().required(), POSTGRES_DB: Joi.string().required(), }), }), ], controllers: [], providers: [], }) export class AppModule {}We also need to create a file that contains the values for the variables we’ve defined above. .env POSTGRES_HOST=localhost POSTGRES_PORT=5432 POSTGRES_USER=admin POSTGRES_PASSWORD=admin POSTGRES_DB=nestjsIn this series, we use PostgreSQL. Because of that, we need the @mikroorm/postgresql package, among others.npm install @mikro-orm/core @mikro-orm/nestjs @mikro-orm/postgresqlWith all of the above, we can create our DatabaseModule that establishes a connection to the database. DatabaseModule.ts import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { MikroOrmModule } from '@mikro-orm/nestjs'; @Module({ imports: [ MikroOrmModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ dbName: configService.get('POSTGRES_DB'), user: configService.get('POSTGRES_USER'), password: configService.get('POSTGRES_PASSWORD'), host: configService.get('POSTGRES_HOST'), port: configService.get('POSTGRES_PORT'), type: 'postgresql', autoLoadEntities: true, }), }), ], }) export class DatabaseModule {} Don’t forget to import the DatabaseModule in the AppModule. Defining a basic entity Thanks to using the autoLoadEntities property, MikroORM loads the entities we define. First, let’s create an elementary entity for a post. To do that, we can use a set of decorators provided by the @mikro-orm/core package. post.entity.ts import { Entity, Property, PrimaryKey } from '@mikro-orm/core'; @Entity() class PostEntity { @PrimaryKey() id: number; @Property() title: string; @Property() content: string; } export default PostEntity;For MikroORM to detect the above entity, we need to register it in the module. posts.module.ts import { Module } from '@nestjs/common'; import { PostsService } from './posts.service'; import PostsController from './posts.controller'; import { MikroOrmModule } from '@mikro-orm/nestjs'; import PostEntity from './post.entity'; @Module({ imports: [MikroOrmModule.forFeature([PostEntity])], controllers: [PostsController], providers: [PostsService], }) export class PostsModule {} Interacting with the entities The above file mentions the PostsController and PostsService. Let’s start by creating the latter. posts.service.ts import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@mikro-orm/nestjs'; import { EntityRepository } from '@mikro-orm/core'; import PostEntity from './post.entity'; @Injectable() export class PostsService { constructor( @InjectRepository(PostEntity) private readonly postRepository: EntityRepository