资源描述
Nest.js快速入门:实现对Mysql单表的CRUD
Nest.js是一个Node.js的后端开发框架,它实现了 MVC模式,也支持了 IOC (自动注入 依赖),比Express这类处理请求响应的库高了一个层次。而且也很容易集成GraphQL、 WebSocket等功能,适合用来做大规模企业级开发。
Nest.js在国内外用的都挺多的,今天我们就来入门下吧:做一个笔记管理功能,实现对mysql 单表的增删改查并提供Restful的接口。
后面要介绍的内容比拟多,我们先来看下最终的效果吧:
, 时长01:07
完整代码上传T github: s://github /QuarkGluonPlasma/nestjs-exercizeNest.js + Typeorm 基础
mysql数据库和Typeorm首先从离前端比拟远的数据库讲起。
在mysql的官网下载mysql,安装并启动服务。
这时候就可以用命令行来写sql操作数据库了。
mysql> show databases; ++| Database|
| hello | information_schema |I mysql|
I nest_cms_api|| performance.schema |
I sys|++
6 rows in set (0.03 sec)mysql>
但是命令行操作不够方便,所以我们还要下载一个有界面的mysql客户端,我这里用的是navicato
OO
视图
其它 用户 查询 备份
对象
« home@hello (local)
Navicat a : 自动运行 4 - ab(
v local
连接 新建查询
(+)
二 about
2
16.00 ►
二 banner
2
16.00 上
home
3
16.00 上
二 note
4
16.00 上
product-categories
11
16.00 上
二 products
7
64.00 上
. user
316.00 ►
名
数据长度
0数件询
H函事查
8 %0
它可以可视化的创立数据库、表等,可以在编辑器里写sql然后执行。比方图中我创立了 hello的数据库和一堆表。
Node.js代码里同样可以连接上数据库服务,然后远程执行sql来对数据库表做增删改查。 但直接执行sql比拟繁琐,能不能我只操作对象,对象属性变了就自动去执行sql来同步数 据库呢?就像vue的数据变了自动同步视图一样。
数据库和对象关系的映射就叫做ORM (Object Relational Mapping),也就是把表映射成对 象,把表与表之间的关联映射成对象之间的关系。之后对对象的操作会通过sql同步到数据 库。
Typeorm就是一个实现orm的框架,可以通过装饰器来描述映射关系,比方@Entity (实 体)、@Column (歹(J)、@PrimaryGeneratedColumn (主键 ID 自动生成)import { Entity, PrimaryGeneratedColumn, Column } from "typeorm”;
〔export class /id: number;
id: number;
| @PrimaryGeneratedColumn()o 1 u m n ()
title: string;
@Column()
content: string;通过装饰器声明了关系,那么在建立了数据库连接之后,我们只需要操作对象,Typeorm就 会自动去执行sql来把变动同步到数据库。
这样,我们对数据库的表的操作和增删改查就实现了。
数据库局部搞定之后,我们再往前看一下处理请求的局部。
请求和 Nest.js处理请求的后端框架我们使用Nest.js,它提供了 ControllerService等划分,这是对MVC 模式的实现。
Controller里面负责处理请求,把处理过的参数传递给service。
Service负责业务逻辑的实现,基于Typeorm的增删改查功能来实现各种上层业务逻辑。
除此以外,Nest.js还划分了 Module,这个Module是逻辑上的模块,和我们常说的文件对 应的模块不同,它包含了 Controller. Service等,是对这些资源的逻辑划分。
AaaModule
Module和 Module之间还可以有依赖关系,也就有imports和exportso 所以,模块的声明就是这样的:
import { Module } from ,@nestjs/common1;@Module({
controllers: [BbbController] providers: [BbbServic^JT^^j exports: [ BbbService]^^^^^})
pxport class BbbModule {}这里通过@Module的装饰器来声明了 Bbb的模块,它依赖了 Aaa模块,也就是在 imports 引入的 AaaModule。controllers 是控制器,包含 BbbController, providers 是提 供商,有service、factory等类型,这里包含BbbService,同时,还导出了 BbbService可 以被其他模块引入。
Controller的声明也是通过装饰器:
@Controller()export class BbbController
Service的声明也是用装饰器,只不过不叫Service,而叫Injectable。
lexport class BbbService至于为什么叫Injectable,就涉及到了 IOC的概念了。
IOC (Inverse Of Control)是控制反转的意思,就是只需要声明你的依赖,不需要创立依赖的 对象,容器会注入给你。
因为所有的对象都是由容器管理的,那么自然就可以在创立对象的时候注入它需要的依赖,这 就是IOC的原理。
Service是可以被作为依赖注入到其他类的实例中去的,所以用Injectable装饰器。
IOC容器AaaModule
AaaModule
AaaController
AaaService
BbbModule
启动IOC容器就是从这个模块开始的:
所有的Module会有一个根 Module作为入口,
mport { NestFactory } from '@nestjs/coreimport { AppModule } from /app.module';
import “reflect-metadata|async function bootstrap。{
const app = await NestFactory.create(AppModule);
await app.listen(3000);bootstrap():
上面就是典型的Nest.js启动代码,从AppModule这个根Module开始创立10C容器, 处理从3000端口发过来的请求。
reflect-metadata模块是用于解析类的装饰器的,因为要给某个类的实例注入依赖就得能解析 出它通过装饰器声明了哪些依赖,然后注入给它。所以要实现I0C需要依赖这个包。
这就是Nest.js大概的设计了 : IOC + MVC,通过IOC容器来管理对象的依赖关系,通过 Controller> Service> Module 来做职责上的划分。
Nest.js 结合 TypeormTypeorm是做把对象的操作通过sql同步为对数据库操作的orm的,而Nest.js是做 Web后端应用的MVC分层以及通过IOC管理对象的创立和依赖的。这俩很自然的可以结 合,结合的方式就是 @nestjs/typeorm 包。
@nestjs/typeorm 包提供了 TypeOrmModule 这个 Module,它有两个静态方法 forRoot> forFeatureoforRoot用于创立数据库连接,传入一些配置参数,在入口 Module引入。
i m p 0 r tsiTypeOrmModule.forRoot({ t y p e: ' m
port: 330 username: ' root
synchronize: t
NotesModule
〔export class AppModule {}
forFeature用于创立不同实体类对应的Repository,在用到该实体的Module里引入。
gModule({imports: [TypeOrmModule.forFeature([Aaa])], controllers : [AaaController ]
exports: [AaaService]export class AaaModule {}
我们知道了 Typeorm和Nest.js都是做什么的和怎么用,简单小结一下:
Typeorm是ORM框架,用于把对象的操作同步为对数据库的操作,会自动执行sql语句。 Nest.js是MVC框架,用于 Web后端应用的逻辑分层,还提供了 Module用来进一步划 分Controller和Serviceo此外,Nest.js提供了 IOC容器,统一管理对象的创立和依赖 关系,根据声明来自动注入依赖。
两者的结合就是通过@nestjs/typeorm的包,它有两个静态方法用于生成Module。
说了这么多,大家可能还理解的不是很清楚,那么我们就来做下笔记管理的实战案例吧。
实战案例
Nest.js样板代码比拟多,自己写还是比拟费事的,@nestjs/cli的命令行工具对这些做了自动 化。
首先要搭工程的骨架,用nest new project-name
然后生成某个Module的代码nest g resource xxx|
生成的代码就是带有Controller> Servicex Module的,并且也有了 CRUD的样板代码。 我们重点来看下Controller的代码:
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';import { XxxService } from /xxx . service
import { CreateXxxDto } f rom/dto/create・xxx. d法〔export class XxxContr
| constructor(private readonly xxxService: XxxService)| create(@Body () createXxxDto: CreateXxxD^Y^^^^^^B
5 . xxxService . create(createXxx5T^77^^^B
return this.xxxService.findAll();
@Get( 1 :icT )
findOne(@Param('id') id: string) {
return this.xxxService.findOne(+id);
j)Patch(1 : id ')
update(@Param(1 id 1) id: string, @Body() updateXxxDto: UpdateXxxDto)
return this.xxxService.update(+id, updateXxxDto);
@Delete(1 : id 1)
return this.xxxService.remove(+id);@Controller的参数可以声明URL路径,@Get> @Post> @Patch> @Delete也可以通过参 数声明URL路径,最终会把两个拼起来。比方/xxx/:id的get方法。
@Get> @Post> @Patch> @Delete分别对应不同的请求方式©@Param是取路径中的参数,@Query是取查询字符串的参数。
@Body是把请求参数设置到对象的属性上,被用来传递数据的对象叫做dto (data transfer object) o再就是返回的对象会被序列化成JSON,不需要手动序列化。
然后再看下Service:
import { Injectable } from '@nestjs/common import { CreateXxxDto } from '•/dto/create-xxx.dto';import { UpdateXxxDto } from '•/dto/update-xxx.dto';
ginjectable()export class XxxService {
create(createXxxDto: CreateXxxDto) {
return 'This action adds a new xxx,;
return 'This action returns all xxx';
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这些service的方法都没有具体实现。
我们引入Typeorm来做数据库的CRUD。
在根模块引入用于数据库连接的Module 在刚创立的模块引入实体对应的Module:
创立笔记实体,用 @Entity标识。并且用 @Column、@PrimaryGeneratedColumn来标识 列和主键。
〔import { Entity, PrimaryGeneratedColumn, Column } from "typeorm〔export class 蓬
| @PrimaryGeneratedColumn|i d : n u m b e
| content:
| createTime| updateTime: Date
之后在service里注入实体对应的操作类Repository,就可以实现对笔记的增删改查了。
用到的dto就是参数对应的对象,他们是实体的一局部属性的集合。比方update dto:
〔export class UpdateNoteDto
createTime: Date;^^^
updateTime: Date;
isDelete: boolean;这样,就实现了对笔记的增删改查。
我们用postman来测试下效果:
运行npm start把工程跑起来可以看到4个接口的路由映射都成功了。
数据库一开始有两条记录:
通过查询接口能正确的查出来:
然后测试下修改接口:
数据库中确实被修改了:
经过测试,对笔记单表的CRUD的功能正常。
, 时长01:07
我们完成了第一个Nest.js的后端应用!
完整代码上传 T github: s://github /QuarkGluonPlasma/nestjs-exercize总结
Typeorm是一个0RM框架,通过映射表和对象的对应关系,就可以把对对象的操作转换为 对数据库的操作,自动执行sql语句。
Nest.js 是一个 MVC 框架,提供了 Module> Controller^ Service 的逻辑划分,也实现了 I0C 模式,集中管理对象和自动注入依赖。
Typeorm 和 Nest.js 的结合使用 @nestjs/typeorm 的包,它提供了一个 TypeormModule 的模块,有forRoot和forFeature两个静态方法。forRoot方法用于生成连接数据库的 Module, forFeature 用于生成实体对应的 Repository 的 Module。
Nest.js有很多样板代码,可以用@nestjs/cli的命令行工具生成,包括整体的和每个Module 的。
总之,理解了 I0C,理解了 Module、Controller^ Service的划分,就算是初 步掌握了 Nest, js,结合Typeorm的ORM框架可以轻松的做数据库表的CRUD。
展开阅读全文