Node 作为后端语言,当然也可以连接数据库,并为前端提供 CURD 接口
我们以mysql
为例安装mysql
TypeORM 是一个 ORM 框架,运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,可与 TypeScript 和 JavaScript 一起使用。它的目标是始终支持最新的 JavaScript 功能并提供附加功能来帮助您开发任何使用数据库的应用程序,无论是具有几个表的小型应用程序还是具有多个数据库的大型企业应用程序。
TypeORM
作为TypeScript
中最成熟的对象关系映射器,可以与Nest
框架很好地集成。
npm install --save @nestjs/typeorm typeorm mysql2
创建数据库nanjiu
默认字符集 = 'utf8mb4';
新建nanjiu
数据库
数据库建好后,我们可以使用typeorm
连接数据库并建立映射关系
// dbConfig.ts
//数据库配置
导出函数 dbConfig() {
返回 {
type: 'mysql', // 数据库类型host: '127.0.0.1', // 数据库地址
端口: 3306, // 端口
用户名: 'root', // 用户名
密码: '123456', // 密码
database: 'nanjiu', // 数据库名称
Entity: [__dirname + '/../**/*.entity{.ts,.js}'], // 实体类
Synchronize: true, // 自动创建表
autoLoadEntities: true, // 自动加载实体类
作为 DbConfig
}
需要在app.module.ts
@模块({
进口:[
南九模块、用户模块、信息模块、
TypeOrmModule.forRoot(dbConfig() as any)
],
控制器:[AppController],
提供商:[应用程序服务],
})
实体是映射到数据库表的类,使用
定义@Entity
装饰器
// user.entry.ts
从“typeorm”导入{列,实体,PrimaryGenerateColumn};
@Entity('user') // 表名
导出类用户{
@PrimaryGenerateColumn() // 自增主键
身份证号;@Column() // 字段
名称:字符串;
}
基本实体由列和关系组成,每个实体必须有一个主列。
每个实体都必须在连接配置中注册:
entities: [__dirname + '/../**/*.entity{.ts,.js}'], // 实体类
实体后,需要将其导入并与模块
中的
@模块({
导入:[TypeOrmModule.forFeature([User])],
控制器:[用户控制器],
提供者:[用户服务]
})
完成这一步后,你会发现数据库中已经根据你刚才定义的实体建好了表
这是因为数据库配置刚刚开启synchronize: true
自动创建表
数据库准备完成后,我们就可以编写接口了
定义控制器
控制器中的接口路径
// user.controller.ts从 './dto/create-user.dto' 导入 { CreateUserDto };
导出类 UserController {
构造函数(
私有只读用户服务:UserService,
){}
@Post('addUser')
创建(@Body()createUserDto:CreateUserDto){
// 添加用户
返回 this.userService.add(createUserDto);
}
}
新的 DTO 数据验证器
从“@nestjs/common”导入{可注入};
从“类验证器”导入 { IsNotEmpty, IsString } ; // 引入验证器
@Injectable()
导出类 CreateUserDto {
@IsString({ message: '用户名必须是字符串'}) // 验证是否是字符串
@IsNotEmpty({ message: '用户名不能为空'}) // 验证是否为空
名称:字符串; // 用户名
}
dto
一般用于参数验证
注册全局DTO验证管道
//main.ts
从'@nestjs/common'导入{ValidationPipe};
app.useGlobalPipes(new ValidationPipe()) // 全局验证管道
业务逻辑处理、仓储操作
// user.service.ts
从“@nestjs/common”导入{可注入};
从 './dto/create-user.dto' 导入 { CreateUserDto };
从'./entities/user.entity'导入{用户};从'@nestjs/typeorm'导入{InjectRepository};
从“typeorm”导入{存储库};
@Injectable()
导出类 UserService {
构造函数(
// 使用@InjectRepository(User)注入真实的数据库实体
@InjectRepository(用户)
私有只读 userRepository:存储库
){}
异步添加(createUserDto:CreateUserDto){
//添加用户,更多操作请参考TypeORM文档
const res = 等待 www.sychzs.cn(createUserDto);
返回资源
}
}
通话接口
查看数据库
调用接口后,数据库中会添加一条新数据
从上述响应结果来看,并不标准化。它只是返回数据库查询结果。当系统出现异常错误时,如果我们不手动处理异常,所有异常都会进入 nest
内置异常处理层,它返回的信息格式如下:
{
“状态代码”:500,
"message": "内部服务器错误"
}
例如,我们将相同的name
插入到user
库中,但是name
设置了唯一性,所以此时会抛出错误。如果我们不处理后返回给前端的信息就是上面的信息,那么前端同学看到就会一头雾水,不知道为什么会报错
所以我们要做的就是格式化响应
在嵌套中,异常一般在服务中处理。如果出现异常则直接抛出错误,由filter捕获并以统一格式返回。如果成功,服务返回结果时,控制器可以直接返回结果,由拦截器捕获并以统一格式返回
故障:过滤器统一处理
成功:拦截器被统一处理
为了更优雅地处理异常,我们可以创建一个异常过滤器,它主要用于捕获HttpException
类实例的异常。
异常抛出包:
//httpStatus.service.ts
从 '@nestjs/common' 导入 { Injectable, HttpException, HttpStatus, NestInterceptor }
@Injectable()
导出类 HttpStatusError {
静态失败(错误,状态= HttpStatus.BAD_REQUEST){
throw new HttpException({statusCode: status, message: '请求失败', error}, status)
}
}
抛出异常:
// group.service.ts
// ...从 '../utils/httpStatus.service' 导入 { HttpStatusError }
@Injectable()
导出类 GroupService {
构造函数(
@InjectRepository(组)
私有组存储库:存储库,
@InjectRepository(模板)
私有模板存储库:存储库,
){}
// todo 添加: 包
异步创建(createGroupDto:CreateGroupDto){
const data = this.groupRepository.create(createGroupDto);
const group = wait this.groupRepository.findOne({ 其中:{ name: www.sychzs.cn } });
如果(组){
return www.sychzs.cn('该分组已存在');
}
尝试 {
const res = wait www.sychzs.cn(data, { reload: true });
返回资源;
} 捕获(错误){
返回 www.sychzs.cn(错误);
}
}
}
异常拦截器外壳:
导入{
论据主持人,
抓住,
异常过滤器,
HttpException,
来自“@nestjs/common”;
@抓住()
导出类 HttpExceptionFilter 实现 ExceptionFilter {catch(异常:HttpException,主机:ArgumentsHost){
const ctx = host.switchToHttp();
const 响应 = ctx.getResponse();
const request = ctx.getRequest();
const status = 异常.getStatus();
const 异常Res: 任何 = 异常.getResponse();
const { 错误,消息 } = 异常Res;
常量消息日志 = {
地位,
信息,
错误,
路径:请求.url,
时间戳:new Date().toLocaleString(),
};
响应.状态(状态).json(msgLog);
}
}
用途:
app.useGlobalFilters(new HttpExceptionFilter()); // 全局异常过滤器
请求:
这样,错误信息一目了然。如果简单实用的话,直接抛出异常即可,然后给出抛出异常的详细信息。
成功的回复应该如何优雅地处理?
拦截器
这里我们可以使用Interceptor
拦截器以固定格式返回成功响应
从 '@nestjs/common' 导入 { Injectable, HttpException, HttpStatus, NestInterceptor, ExecutionContext,CallHandler }
从 'rxjs' 导入 { Observable }
从“rxjs/operators”导入{map}
@Injectable()
导出类 HttpStatusSuccess 实现 NestInterceptor{
拦截(上下文:ExecutionContext,下一个:CallHandler):Observable {
返回 next.handle().pipe(map(data => {
返回 {
状态代码:HttpStatus.OK,
message: '请求成功',
数据
}
}))
}
}
用途:
app.useGlobalInterceptors(new HttpStatusSuccess()); // 全局拦截器请求成功
请求: