nest 练习demo初级版

2022/03/13 后端 共 4775 字,约 14 分钟

疫情

刚刚刷到朋友圈,深圳地铁停运,公交停运,封闭式管理,居家办公三天。而我在上海也有不少同事需要在家隔离14天,之后才能来公司上班。好几年了,啥时候疫情能够不要如此的影响人们的生活呀。

前几天和大三时候认识的前端网友聊天,这么多年没断联系。如今都已经工作四年+了,彼此都有了自己的发展方向,我继续扎根技术基层,他看算法,准备自己带团队,走管理成。当初起点一样,有着一样的目标,多年后大家都有了自己新的目标。祝愿彼此在彼此的选择上越来越好,道路越来越光明。

背景

今年开始接触到后段,技术选型是:nest+typeorm+mysql,最开始拿到项目的时候,是懵逼的,我认识每一个单词,但是他们一顿组合我就不认识了。花了大概一周的时间,看了基本的语法,照葫芦画瓢勉勉强强能够把简单的需求做出来,但是很多东西不明白为啥要这么写。周末整理了一下简单的dome,懂了一点点,所以就写下来,方便之后看。

语法

任何框架的学习开始是语法,类比学习,雷同记忆语法上手还是很快的。语法熟悉之后,就要上手做项目,去感受语法的魔力,真正的开始一个走向学习的道路。

关于语法我就不在一一介绍了,官方文档,我前面的文章都有写到,可以参考前面的学习。

准备开始

为了方便测试我这里推荐一个工具Postman,用来接口测试工作,模拟各种api的请求

npm i -g @nestjs/cli
nest new project-name

一个 nest 的后端项目建好了

接下来我们需要连接数据库,创建数据表,然后操作数据表

连接数据库

一个项目一般都会有好几个环境,比如测试环境,预发环境,线上环境。所以在连接数据库的时候,我们需要根据不同的环境连接不同的数据库。

最简单直白的连接

  1. 在根模块使用 nestjs 的 typeorm 模块 TypeOrmModule.forRoot 连接数据库
// app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import * as path from 'path';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '12345678',
      database: 'sunseekers',
      entities: [path.join(__dirname, '/**/*.entity{.ts,.js}')],// 需要在模块的forRoot()方法的选项中将它插入entities数组中来让 TypeORM知道它的存在
      synchronize: true,
    }),
    UserModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

配置环境

  1. 根目录创建ormconfig.json文件,然后不带参数的调用
// app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import * as path from 'path';

@Module({
  imports: [
    TypeOrmModule.forRoot(),
    UserModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

// ormconfig.json
{
  "type": "mysql",
  "host": "localhost",
  "port": 3306,
  "username": "root",
  "password": "root",
  "database": "test",
  "entities": ["src/**/**.entity{.ts,.js}"],// 使用哪些实体,一般是全部实体都导入进来
  "synchronize": true
}

动态模块,自动读取.env文件变量

要开始使用它,我们首先安装所需的依赖项。

npm i --save @nestjs/config

安装完成之后,我们需要导入ConfigModule模块。通常,我们在根模块AppModule中导入它,并使用.forRoot()静态方法导入它的配置。

import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import * as path from 'path';

@Module({
  imports: [
    TypeOrmModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        host: configService.get(`MYSQL_HOST`),
        port: +configService.get<number>(`MYSQL_PORT`),
        username: configService.get(`MYSQL_USERNAME`),
        password: configService.get(`MYSQL_PASSWORD`),
        database: configService.get(`MYSQL_DATABASE`),
        entities: [path.join(__dirname, '../../**/*.entity{.ts,.js}')],
        synchronize: false,
      }),
      inject: [ConfigService],
    }),],
})
export class AppModule {}

.env 文件里面的变量全部用大写类似这样

DATABASE_USER=test
DATABASE_PASSWORD=test

到此就介绍了几种连接数据库的方式,一般情况都是推荐用最后一种的。

创建数据表

// user.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity('user', { schema: 'sunseekers' })
export class User {
  @PrimaryGeneratedColumn({ type: 'int', name: 'id', unsigned: true })
  id: number;

  @Column('varchar', { name: 'name', nullable: true, length: 255 })
  name: string | null;

  @Column('bigint', {
    name: 'create_time',
    comment: '创建时间',
  })
  create_time: number | null;
}

这里创建了一张user表,在sunseekers库下面

连接实体(连接数据表)

告诉 module,我现在要用哪一张表(需要导入哪个实体)

src/user/user.module.ts

import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from '../common/entities/user.entity';
import { UserController } from './user.controller';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService],
})
export class UserModule {}

使用 @InjectRepository()装饰器将 user 注入到 UsersService 中,然后开始操作实体

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../common/entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly user: Repository<User>,
  ) {}

  // 查找这张表的所有数据
  async findAll() { 
    return await this.user.find();
  }
  // 查找指定id的用户
  async find(id: number) {
    return await this.user
      .createQueryBuilder()
      .where('id=:id', { id })
      .getOne();
  }
  // 插入一条数据
  async insert(createDto: CreateUserDto) {
    return await this.user
      .createQueryBuilder()
      .insert()
      .values({
        ...createDto,
        create_time: Date.now(),
      })
      .execute();
  }
  // 更新一条数据
  async update(createDto: CreateUserDto, id: number) {
    const res = await this.user
      .createQueryBuilder()
      .update(createDto)
      .where('id=:id', { id })
      .execute();
    return res;
  }
  // 删除一条数据
  async delete(id: number) {
    return await this.user
      .createQueryBuilder()
      .delete()
      .where('id=:id', { id })
      .execute();
  }
}

到此我们就实现了实体的增删查改了,再加上路由的操作,简单的功能就已经实现了,路由操作的不就在贴代码了,比较简单

接下来我还讲什么?

上面讲的只是基本的一张表的操作,用到的api也相对简单,在一个项目中需要用到和学到的东西远远不止这些,以后都会慢慢的讲

  1. 如何处理事务?

  2. InjectConnection和InjectRepository的区别?

  3. 如何进行多表复杂的查询?

  4. RepositoryAPI 和 Connection API 等等的区别

  5. 等等等


在技术的历史长河中,虽然我们素未谋面,却已相识已久,很微妙也很知足。互联网让世界变得更小,你我之间更近。

在逝去的青葱岁月中,虽然我们未曾相遇,却共同经历着一样的情愫。谁的青春不曾迷茫或焦虑亦是无奈,谁不曾年少过

在未来的日子里,让我们共享好的文章,共同学习进步。有不错的文章记得分享给我,我不会写好的文章,所以我只能做一个搬运工

我叫 sunseekers(张敏) ,千千万万个张敏与你同在,18年电子商务专业毕业,毕业后在前端搬砖

如果喜欢我的话,恰巧我也喜欢你的话,让我们手拉手,肩并肩共同前行,相互学习,互相鼓励

文档信息

Search

    Table of Contents