NestJS build blog system (3) – using TypeORM+Mysql to achieve data persistence

preface

In this section we use TypeORM + Mysql for data persistence.

TypeORM is an ORM framework that runs on NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, Expo, and Electron platforms. Works with TypeScript and JavaScript (ES5,ES6,ES7,ES8). Its goal is to always support the latest JavaScript features and provide additional features to help you develop any application that uses a database, whether it’s a small application with just a few tables or a large enterprise application with multiple databases.

You can also choose Squelize ORM

Environment configuration

Mysql installation

I won’t elaborate on the Mysql installation method here. By the way, amway is an easy way to configure, which is also the way I am using. Use Docker to run mysql. Github.com/huihuipan/e… This database is configured with Mysql, Mongodb, Redis, Nginx, Jenkins, YAPI and other services. You can choose your own services according to your own needs.

Software part

The software uses database tools such as Navicat/dbeaver debugging requests using Postman or yAPI provided in the environment above

Write the code

Install dependencies

Using TypeORM and mysql requires the following packages to be installed in your project

npm install --save @nestjs/typeorm typeorm mysql2
Copy the code

The reference configuration

First we reference TypeOrmModule in app.module, which is provided by @nestjs/ TypeOrm

// src/app.modules.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ArticleModule } from './modules/article/article.module';
import { TypeOrmModule } from '@nestjs/typeorm'
@Module({
  imports: [
    // Configure the database using TypeORM
    TypeOrmModule.forRoot({
      type: 'mysql'.host: 'localhost'.port: 3306.username: 'root'.password: '888888'.database: 'test'.entities: ["dist/modules/**/*.entity{.ts,.js}"].synchronize: true,
    }),
    ArticleModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Copy the code

Create Entity Entity

Entity is a model decorated with the @Entity decorator. TypeORM creates database tables for such models.

New file SRC/modules/article/entity/article entity. Ts

// src/modules/article/entity/article.entity.ts

import { 
  Entity, 
  Column, 
  PrimaryGeneratedColumn, 
  UpdateDateColumn,
  CreateDateColumn,
  VersionColumn,
} from 'typeorm';

@Entity(a)export class Article {
    / / the primary key id
    @PrimaryGeneratedColumn(a)id: number;
  
    // Create time
    @CreateDateColumn(a)createTime: Date
  
    // Update time
    @UpdateDateColumn(a)updateTime: Date
  
    / / soft delete
    @Column({
      default: false
    })
    isDelete: boolean
  
    // Number of updates
    @VersionColumn(a)version: number
  
    // Title of the article
    @Column('text')
    title: string;

    // The description of the article
    @Column('text')
    description: string;

    // The content of the article
    @Column('text')
    content: string;
}
Copy the code

Use DTO

Here’s what NestJS says about Dtos

DTO (Data Transfer Object) mode. A DTO is an object that defines how data is sent across a network. DTO patterns can be defined using TypeScript interfaces or simple classes. Interestingly, we recommend using classes here. Why is that? Classes are part of the JavaScript ES6 standard, so they are retained as actual entities in compiled JavaScript. On the other hand, because TypeScript interfaces are removed during the transformation, Nest cannot reference them at run time. This is important because features such as pipes provide more possibilities for accessing a variable’s metatype at run time.

In Java

DTO: Data transfer object, originally designed to provide coarse-grained data entities for distribution and reduce the number of calls to improve performance and reduce network stress.

Simply put, it defines a data that acts like an entry to a method, but also makes it easy to do other things. For example, our form validation can be used in dtos.

Create the following files

// src/modules/article/dto/list.dto.ts

export class ListDTO {
  readonly page: number;
  readonly pageSize: number;
}
Copy the code
// src/modules/article/dto/id.dto.ts

export class IdDTO {
  readonly id: number
}
Copy the code
// src/modules/article/dto/article-create.dto.ts

export class ArticleCreateDTO {
  readonly title: string;
  readonly description: string;
  readonly content: string;
}
Copy the code
// src/modules/article/dto/article-edit.dto.ts

export class ArticleEditDTO {
  readonly id: number;
  readonly title: string;
  readonly description: string;
  readonly content: string;
}
Copy the code

Dtos are used in the controller

import { 
  Controller, 
  Body, 
  Query,
  Get, 
  Post,
} from '@nestjs/common';
import { ArticleService } from './article.service';
import { ArticleCreateDTO } from './dto/article-create.dto';
import { ArticleEditDTO } from './dto/article-edit.dto';
import { IdDTO } from './dto/id.dto';
import { ListDTO } from './dto/list.dto';

@Controller('article')
export class ArticleController {
  constructor(
    private articleService: ArticleService
  ) {}

  @Get('list')
  getMore(
    @Query() listDTO: ListDTO,
  ) {
    return this.articleService.getMore(listDTO)
  }

  @Get('info')
  getOne(
    @Query() idDto: IdDTO
  ) {
    return this.articleService.getOne(idDto)
  }

  @Post('create')
  create(
    @Body() articleCreateDTO: ArticleCreateDTO
  ) {
    return this.articleService.create(articleCreateDTO)
  }

  @Post('edit')
  update(
    @Body() articleEditDTO: ArticleEditDTO
  ) {
    return this.articleService.update(articleEditDTO)
  }

  @Post('delete')
  delete(
    @Body() idDto: IdDTO,
  ) {
    return this.articleService.delete(idDto)
  }
}

Copy the code

Define those repositories to use in article. Module

import { Module } from '@nestjs/common';
import { ArticleService } from './article.service';
import { ArticleController } from './article.controller';
import { Article } from './entity/article.entity';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
  imports: [
    TypeOrmModule.forFeature([Article]),
  ],
  providers: [ArticleService],
  controllers: [ArticleController]
})
export class ArticleModule {}
Copy the code

Also modify our service to use TypeORM to access data

import { Injectable } from '@nestjs/common';
import { ArticleCreateDTO } from './dto/article-create.dto';
import { ArticleEditDTO } from './dto/article-edit.dto';
import { IdDTO } from './dto/id.dto';
import { ListDTO } from './dto/list.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Article } from './entity/article.entity';

@Injectable(a)export class ArticleService {
  list: any[];
  
  constructor(
    @InjectRepository(Article)
    private readonly articleRepository: Repository<Article>,
  ) {
    this.list = []
  }

  async getMore(
    listDTO: ListDTO,
  ) {
    const { page = 1, pageSize = 10 } = listDTO
    const getList = this.articleRepository
      .createQueryBuilder('article')
      .where({ isDelete: false })
      .select([
        'article.id'.'article.title'.'article.description'.'article.createTime'.'article.updateTime',
      ])
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getMany()

    const list = await getList
    return list
  }

  async getOne(
    idDto: IdDTO  
  ) {
    const { id } = idDto
    const articleDetial = await this.articleRepository
      .createQueryBuilder('article')
      .where('article.id = :id', { id })
      .getOne()
    return articleDetial;
  }

  async create(
    articleCreateDTO: ArticleCreateDTO
  ):Promise<Article>{
    const article = new Article();
    article.title = articleCreateDTO.title
    article.description = articleCreateDTO.description
    article.content = articleCreateDTO.content
    const result = await this.articleRepository.save(article);
    return result
  }

  async update(
    articleEditDTO: ArticleEditDTO
  ): Promise<Article>{
    const { id } = articleEditDTO
    let articleToUpdate = await this.articleRepository.findOne({ id })
    articleToUpdate.title = articleEditDTO.title
    articleToUpdate.description = articleEditDTO.description
    articleToUpdate.content = articleEditDTO.content
    const result = await this.articleRepository.save(articleToUpdate)
    return result
  }
  
  async delete (
    idDTO: IdDTO,
  ) {
    const { id } = idDTO
    let articleToUpdate = await this.articleRepository.findOne({ id })
    articleToUpdate.isDelete = true
    const result = await this.articleRepository.save(articleToUpdate)
    return result
  }
}
Copy the code

reference

  • NestJS
  • NestJS Chinese website
  • TypeORM
  • SquelizeORM
  • Github.com/huihuipan/e…
  • Code for this section

A series of

  • NestJS build blog system (a) – build a framework
  • NestJS build blog system (2) – write static article CURD