Nest.js is a Node.js-based back-end development framework that implements the MVC pattern, which is the layering of Model, View, and Controller. It also supports IOC, which is the automatic injection of dependencies, and is one level higher than libraries like Express that handle request responses. It is also easy to integrate GraphQL, WebSocket and other functions, suitable for large-scale enterprise development.

Nest.js is widely used at home and abroad. Today we will start with a note management function to realize the addition, deletion, change and check of mysql single table and provide a Restful interface.

Full code: github.com/QuarkGluonP…

Nest.js + Typeorm base

Mysql database and Typeorm

Let’s start with the database, which is far away from the front end.

Download mysql from the mysql website, install mysql, and start the service.

At this point, you can use the command line to write SQL operation database.

But the command line is not convenient enough, so we need to download a mysql client with an interface. I used Navicat here.

It can visually create databases, tables, etc. It can write SQL in the editor and execute it. For example, I created a hello database and a bunch of tables.

Node.js code can also connect to the database service, and then remotely execute SQL to add, delete, change and query the database table.

But directly execute SQL is more tedious, can I only operate on the object, object properties change to automatically execute SQL to synchronize the database? Just like vUE’s data changes to the auto-sync view.

Relational Mapping between databases and objects is called Object Relational Mapping (ORM), that is, Mapping tables into objects, and Mapping the associations between tables into relationships between objects. Subsequent operations on objects are synchronized to the database through SQL.

Typeorm is a framework that implements ORM and can describe mappings with decorators such as @Entity, @column, @primaryGeneratedColumn (primary key ID generated automatically)

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class Note{

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    title: string;

    @Column()
    content: string;
}
Copy the code

With the relationship declared through the decorator, after the database connection is established, all we need to do is manipulate the object, and Typeorm automatically executes SQL to synchronize the changes to the database.

In this way, we on the database table operation and add, delete, change and check will be realized.

With the database part out of the way, let’s move on to the part that handles requests.

HTTP requests and Nest.js

The back-end framework for processing requests we use Nest.js, which provides Controller, Service, and other partitions, which is an implementation of the MVC pattern.

The Controller handles the request and passes the processed parameters to the Service.

Service is responsible for the implementation of business logic, based on Typeorm to achieve a variety of upper-level business logic.

In addition, Nest.js also divides modules. This Module is a logical Module, which is different from the modules corresponding to files. It contains Controller, Service, etc., which is a logical division of these resources.

Modules can also have dependencies between modules, such as imports and exports.

So, the module declaration looks like this:

import { Module } from '@nestjs/common';

@Module({
  imports: [AaaModule],
  controllers: [BbbController],
  providers: [BbbService],
  exports: [BbbService]
})
export class BbbModule {}
Copy the code

The Bbb Module is declared via the @Module decorator, which relies on the AaaModule, the AaaModule introduced in imports. Controllers (controllers), providers (Factory, Service, controllers), providers (controllers), providers (controllers), providers (controllers), providers (factory, Providers), providers (controllers), providers (factory, providers), providers (controllers), providers (factory, providers), providers (controllers), providers (factory, providers)

The Controller declaration is also via decorator:

@Controller(a)export class BbbController {}Copy the code

Service declarations are also called Injectable instead of Service.

@Injectable(a)export class BbbService {}Copy the code

Injectable refers to the IOC concept.

Inverse Of Control (IOC) stands for Inverse Of Control, which means you only need to declare your dependencies, you don’t need to create dependent objects, and the container will inject them into you.

Because all objects are container-managed, it is natural to inject the dependencies that an object needs when it is created, which is how IOC works.

Services can be injected as dependencies into instances of other classes, so use the Injectable decorator.

All modules have a root Module as an entry point from which the IOC container is started:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import "reflect-metadata";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();
Copy the code

This is the typical Nex.js startup code that creates an IOC container from the root Module of AppModule to handle requests from port 3000.

The reflect-metadata module is used to resolve class decorators, because injecting dependencies into an instance of a class requires being able to resolve which dependencies it declares through the decorator and then inject them into it. So implementing IOC relies on this package.

This is the general design of Nex.js: IOC + MVC, which manages object dependencies through IOC container and divides responsibilities through Controller, Service and Module.

Nest. Integrating js Typeorm

Typeorm does the synchronization of object operations through SQL to ORM operations on the database, while Nex.js does the MVC layering of Web back-end applications and manages object creation and dependency through IOC. The two naturally combine in the @nestjs/ Typeorm package.

The @nestjs/ Typeorm package provides TypeOrmModule, which has two static methods forRoot and forFeature.

ForRoot is used to create a database connection, passing in some configuration parameters, imported in the entry Module.

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql'.host: 'localhost'.port: 3306.username: 'root'.password: 'Your password'.database: 'database name'.synchronize: true
    }),
    NotesModule
  ]
})
export class AppModule {}
Copy the code

ForFeature is used to create a Repository for each entity class and is introduced in modules that use that entity.

@Module({
  imports: [TypeOrmModule.forFeature([Aaa])],
  controllers: [AaaController],
  providers: [AaaService],
  exports: [AaaService]
})
export class AaaModule {}
Copy the code

We know what Typeorm and Nest.js do and how to use them. Here’s a quick summary:

Typeorm is an ORM framework that synchronizes operations on objects to operations on databases, automatically executing SQL statements.

Nest.js is an MVC framework for logical layering of Web back-end applications. It also provides modules to further divide controllers and services. In addition, Nest.js provides an IOC container that manages object creation and dependencies, automatically injecting dependencies based on declarations.

The combination of the two is the @nestjs/ Typeorm package, which has two static methods for generating modules.

Having said so much, we may still understand is not very clear, so we will make the actual case of note management.

Practical cases

The @nestjs/ CLI command line tool automates the nestjs boilerplate code.

The first step is to build the skeleton of the project

nest new project-name
Copy the code

Then generate code for a Module

nest g resource xxx
Copy the code

The generated code comes with Controller, Service, Module, and CRUD boilerplate code.

Let’s focus on the Controller code:

import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { XxxService } from './xxx.service';
import { CreateXxxDto } from './dto/create-xxx.dto';
import { UpdateXxxDto } from './dto/update-xxx.dto';

@Controller('xxx')
export class XxxController {
  constructor(private readonly xxxService: XxxService) {}

  @Post(a)create(@Body() createXxxDto: CreateXxxDto) {
    return this.xxxService.create(createXxxDto);
  }

  @Get(a)findAll() {
    return this.xxxService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.xxxService.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string.@Body() updateXxxDto: UpdateXxxDto) {
    return this.xxxService.update(+id, updateXxxDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.xxxService.remove(+id); }}Copy the code

The @controller parameter can declare the URL path. The @GET, @post, @patch, and @delete parameter can also declare the URL path. For example, the/XXX /:id get method.

@GET, @POST, @patch, and @delete correspond to different request modes.

@param is the parameter to fetch the path, and @query is the parameter to fetch the Query string.

@body is to set the request parameters to the properties of the object, which is used to transfer data is called DTO (Data Transfer Object).

Furthermore, the returned object is serialized to JSON without manual serialization.

Then look at Service:

import { Injectable } from '@nestjs/common';
import { CreateXxxDto } from './dto/create-xxx.dto';
import { UpdateXxxDto } from './dto/update-xxx.dto';

@Injectable(a)export class XxxService {
  create(createXxxDto: CreateXxxDto) {
    return 'This action adds a new xxx';
  }

  findAll() {
    return `This action returns all xxx`;
  }

  findOne(id: number) {
    return `This action returns a #${id} xxx`;
  }

  update(id: number, updateXxxDto: UpdateXxxDto) {
    return `This action updates a #${id} xxx`;
  }

  remove(id: number) {
    return `This action removes a #${id} xxx`; }}Copy the code

None of these service methods are implemented concretely.

We introduced Typeorm to do CRUD for the database.

Introduce a Module for database connections into the root Module

Add the entity Module to the newly created Module:

Create note Entity identified with @entity. And use @column, @primaryGeneratedColumn to identify the Column and primary key.

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity(a)export class Note{

    @PrimaryGeneratedColumn(a)id: number;

    @Column(a)title: string;

    @Column(a)content: string;

    @Column(a)createTime: Date;

    @Column(a)updateTime: Date;

    @Column(a)isDelete: boolean;
}

Copy the code

Add, delete, modify, and query notes by injecting the entity’s Repository into the service.

The Dtos used are the objects corresponding to the parameters, which are a collection of attributes that are part of the entity. For example, update DTO:

export class UpdateNoteDto {
    title: string;

    content: string;

    createTime: Date;

    updateTime: Date;

    isDelete: boolean;
}
Copy the code

In this way, the increase, deletion, change and check of notes are realized.

Let’s use Postman to test the effect:

Run NPM start to get the project running

It can be seen that the route mapping of the four interfaces is successful.

The database starts with two records:

By querying the interface, the following information can be found:

Then test the modify interface:

The database is indeed modified:

After testing, the CRUD function of the single table of notes is normal.

We finished our first nest. js back-end application!

The full code is uploaded to github: github.com/QuarkGluonP…

conclusion

Typeorm is an ORM framework, by mapping the mapping between tables and objects, you can transform the operation of objects into the operation of databases, and automatically execute SQL statements.

Nest.js is an MVC framework, which provides logical division of Module, Controller and Service. It also implements IOC mode, centralized management of objects and automatic injection of dependencies.

The combination of Typeorm and Nest.js uses the @nestjs/ Typeorm package, which provides a module of TypeormModule with two static methods forRoot and forFeature. The forRoot method is used to generate the Module that connects to the database, and forFeature is used to generate the Repository Module that corresponds to the entity.

Nestjs has a lot of boilerplate code that can be generated using the @nestjs/cli command-line tool, both overall and per Module.

In a word, with an understanding of IOC and the division of Module, Controller and Service, even with a preliminary grasp of Nest.js, the ORM framework combined with Typeorm can easily do CRUD of database tables.

Nest.js is one of the more powerful and popular back-end frameworks, so it’s worth learning about. In this article, we entered the next door and will continue to go further.