Nest从零开始增删改查

374 阅读10分钟

大家好,我是tomato,最近闲来无事,准备看一看Nest.js相关内容,看了一遍文档,实际留在脑子里的倒没有多少。

最好的提升方式莫不过从demo开始,因此这篇攻略,送给那些想用Nest写后端的宝子们。

本攻略整体思路从数据库开始,一直到后台管理系统的增删改查

对于我个人也算是一种记录,那么闲话少叙,请尽情享用吧!

参考:传送门一

微信图片_20241107095518.jpg

对于数据库的选择,这里选择MySql,安装的方法网上有很多,这里放一篇博文,直接看这个就好,一步步走没问题: MySql安装一步到位 (如果没装上,评论区留言,我帮你去看)

除了MySql,对于前端不熟悉数据库的宝子,同样需要一款图形化数据库管理工具,我这里选择Navicat,你可以直接使用。

至于Navicat的作用,形象一点来讲,就好比在使用git的时候,你不想来回输入指令,无界面操作可能会遇到很多坑,因此部分人选择使用小乌龟这种工具,有界面、功能提示也很明显,Navicat的作用就在此,大大简化MySql操作过程。

Navicat安装包放在下面,步骤很简单,一路无脑下一步即可,需要注意的是放置路径,理论上放哪儿都行,干就完了。

Navicat安装包(密码:wyhh)

Navicat安装之后,是有使用期限的,所以需要破解版,你可以直接看这个:(同样是实操可行,一步步走,有问题的话,直接把报错信息复制,去搜索查找,解决方案很完善)

Navicat破解教程

目前咱们数据库有了,操作数据库的图形化界面也有了,接下来就需要安装并使用Nest.js了。

老规矩,先在cmd命令窗口(Win+R),终端运行指令:

npm i -g @nestjs/cli // 全局安装Nest(这个指令的作用就是给你,全局安装 NestJS CLI)

再运行第二个指令:

nest new project-name(搞完这一步,脚手架就搭建好了)

在CMD界面,它会问你用什么安装包,我这里用的是pnpm,所以接下来再安装任何插件,你直接用pnpm就行。

image.png

接下来,你就可以在vscde,直接开始写后端服务了。

image.png

这个是文件目录,你在刚创建完之后,会比我少几个,问题不大,后面都会有的。

项目目录,多数和vue项目类似,比如node_modules等,保证干货,就不多赘述啦。

大家需要注意四个文件,main.ts是入口文件,和前端一样。app.service.ts文件,用来写接口的实际逻辑。在这里你会定义各种方法,各种增删改查操作,都在这里写。

app.controller.ts文件,它的作用主要是用来调用app.service.ts,也就是说方法都写在后者,然后前者负责调用,关系是这样的。

app.module.ts主要是做相关配置的文件,后面详谈,一通大白话讲完,相信你已经很清晰了。

项目启动方式如下(没有任何error类报错,就是成功了)

npm/pnpm start

image.png

这里我教你在哪看项目首页:

一般项目刚启动,都是http://localhost:9080 这个地址,你在浏览器直接打开就行。

然后你就会看到经典的hello world!页面,这里注意我的网址,是可以随意更改的,后面讲。

image.png

hello world也可以修改,对应的代码在这里。

image.png

如何修改页面的地址?

首先在本地起项目,“http://localhost:”是固定的 ,再往后对于端口的定义,要去主文件更改(不是唯一的方式)

代码都一样,你可以跟着走,端口我定义为了1910,前面的process.env.PORT是环境变量,前端里也有,通用的,此时没有,所以端口为1910。

image.png

可我后面是什么呢?怎么写路由?

image.png

还是回到主文件,定义你的固定路由,类似前端的baseUrl(你找到对应位置,写一下,自行感受,这里我写的是api)

image.png

但是问题来了,不同的数据库,不同的表,从路径上是不是要区分?比如这个接口,表叫post,那么对应的路由也得变,在下面这里改。

image.png

上面提到,app.controller.ts是调用接口逻辑的文件,那么不同接口,是不是也得变一个路由?(看图)

image.png

就是这个叫hello的路由,说完这些,就拼起来了。下图你也就明白是什么意思了,本地+端口+baseUrl+表名+接口路径

image.png

我知道你现在很想写接口,但你别急,还差两步,后面你会更丝滑(对于nest的初学,先把实际的搞明白,先写起来,剩下所谓的理论部分,慢慢啃就行,听完上面的内容,对于其它你目前“非重要”的疑问,暂时保留,因为不重要)

最开始讲到,咱们mysql有了,操作mysql的图形化工具navicat有了,那么数据库这边怎么用呢?

一般情况下,打开电脑,你得先把mysql启动起来,只有启动才能连接。

指令如下:

net start mysql

需要提一句的是,最开始,你在安装mysql的过程中,一定设置了环境变量,环境变量的作用就是“全局化”,直白一点,我不用非得进入到mysql的文件夹,再打开cmd,相反,我随便打开cmd,输入上述命令,就能启动。

所以这一步有的人会启动不了,其实就是全局化的问题,不妨做个实验,你去mysql安装路径,打开cmd试一试,一定是好使的,所以如果报错了,复制一下错误,去网上搜索,一个指令就可以解决。(不多提)

如下为启动成功案例:

image.png

启动之后,你再用navicat把数据库连上:

image.png

随后你会进入到这个界面:

image.png

固定的不动,连接名随便起,这个不是服务器名字,是你的连接名字。密码是你的mysql安装时设置的密码。

连接成功之后,你会看到我叫blog的数据库亮了,变绿了,那就是成功了。上图左下角有个测试连接,能测试出你是否成功连上数据库。

这里面有几个小坑,有的人连不上,细心一点,把报错cv一下,搜一搜就出来了。

image.png

上图中,post,user,profile都是我的表。

好,那么mysql和navicat这两块拿下,接下来咱们回到vscode代码中。

你需要安装最后一个插件,那就是prisma,它是一个开源的ORM框架,复杂的理论不说了,没必要,也挺晦涩的。

其实它的作用就是帮你定义数据库的数据,然后把数据往数据库里面插入,你用这个,就可以在vscode里面,写js代码,操作数据库,就这么直白。

同样,prisma功能很强大,需要日后你去慢慢探索,下面是它的官方文档,以后慢慢看。

prisma官方文档

安装prisima有两个指令,第一步先安装,第二步就是初始化,这个初始化其实和git初始化类似,可以帮助你快速理解。

pnpm install prisma // 安装

npx prisma init // 初始化

初始化成功后,你的项目会多两个文件,如图:

image.png

其中这个schema.prisma文件,作用就是往里写逻辑,写数据,然后放在数据库里,够直白了吧,如图。

它上面的migrations记录了一些操作记录,暂时不用管,日后你慢慢探索。

image.png

下面这个env,其实就是前端的环境变量,如图:

image.png

了解这些之后,你要做的是,把prisma和nest连接上,这样才能使用,这一块其实在文档里写的很明白了。

image.png

你要做的是,去env文件,把url定义好,如图:

image.png

最前面的mysql固定,咱们用的就是,://root固定,在本地,后面的a1326104255是数据库密码,再往后的3306就是端口号,上面我已经教你怎么设置了,再往后直接照抄。(细节去看一下文档就行)

"mysql://root:a1326104255@localhost:3306/blog?schema=public"

做完这些,终于可以写接口了,首先先往你的schema.prisma文件里,写点数据,我给你一个例子,先cv再感悟:

这个没有的先加上,和上述连接是对应的,能映射上,我一起给你放上,直接cv。

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model Post {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  title     String   @db.VarChar(255)
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}

model Profile {
  id     Int     @id @default(autoincrement())
  bio    String?
  user   User    @relation(fields: [userId], references: [id])
  userId Int     @unique
}

model User {
  id      Int      @id @default(autoincrement())
  email   String   @unique
  name    String?
  posts   Post[]
  profile Profile?
}

举个例子,model是固定写法,在prisma里面都有,后面比如Profile是mysql的表名,大括号对象里的是“插入的内容”。

另外你会发现,页面代码都是白色的,看着冷冰冰的,连代码提示都没有,因此,你需要下载一个插件。(下载之后就好啦)

image.png

接着你需要把写的内容,插入数据库中,给你两个命令:

npx prisma migrate dev

npx prisma migrate dev --name test

第一个是根据schema.prisma文件,生成并执行sql,往里插数据

第二个同理,区别在于可以指定名字。

选一个就行。

咱们去navicat里面看,图一是咱们插入的表,图二为对应的数据,我这里数据:

image.png

image.png

数据库也有数据了,接下来终于到了CURD环节,开始写接口!

写接口之前,prisma需要一步操作,那就是注入客户端。这里涉及到三个文件,module、controller和service。

在module里面,你得注册prisema,代码如下:(先不要着急cv,我告诉你在哪)

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PostsModule } from './posts/posts.module';

import { PrismaClient } from '@prisma/client';
// import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [PostsModule],
  controllers: [AppController],
  providers: [AppService, PrismaClient],
})
export class AppModule { }

import引入,再进行注册。

image.png

然后是service,你同样需要引入prisma,这里我写了点接口,你可以先直接用,然后后面告诉你为什么这么写。(对照一下,和你的有什么区别,别弄错了)

image.png

import { Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';


@Injectable()
export class AppService {
  constructor(private readonly appService: PrismaClient) { }
  getHello(): string {
    return 'Hello World!';
  }

  async findAllPosts() {
    return this.appService.post.findMany();
  }

  async findPostsById(id: number) {
    return this.appService.post.findUnique({
      where: { id },
    });
  }

  async createPosts(data: any) {
    return this.appService.post.create({
      data,
    });
  }

  async updatePosts(id: number, data: any) {
    return this.appService.post.update({
      where: { id },
      data,
    });
  }

  async deletePosts(id: number) {
    return this.appService.post.delete({
      where: { id },
    });
  }


}

接口逻辑写完,那么我们需要在控制器上引入,也就是controller文件。

image.png

import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { AppService } from './app.service';

import { Post as MyPost } from '@prisma/client';


@Controller('posts')
export class AppController {
  constructor(private readonly appService: AppService) { }



  @Get()
  async findAll(): Promise<MyPost[]> {
    return this.appService.findAllPosts();
  }
  @Get('hello')
  getHello(): string {
    return this.appService.getHello();
  }

  @Get(':id')
  async findOne(@Param('id') id: string): Promise<MyPost | null> {
    return this.appService.findPostsById(+id);
  }

  @Post()
  async create(@Body() postData: { title: string; content?: string; published?: boolean; authorId: number }): Promise<MyPost> {
    return this.appService.createPosts(postData);
  }


  @Put(':id')
  async update(@Param('id') id: string, @Body() updateData: { title?: string; content?: string; published?: boolean }): Promise<MyPost | null> {
    return this.appService.updatePosts(+id, updateData);
  }

  @Delete(':id')
  async remove(@Param('id') id: string): Promise<MyPost | null> {
    return this.appService.deletePosts(+id);
  }


}

随后咱们可以找一个接口,比如下面这个:

image.png

用apiFox试一下:

image.png

再打开navicat去看一下表数据:

image.png

已经成功添加,其余删改查,你同样可以去看里面的代码,小demo实例都在里面。

目前算是基本完成,后续完善待更新,fighting!