会员登录 - 用户注册 - 设为首页 - 加入收藏 - 网站地图 【NestJS系列】连接数据库及优雅地处理响应!

【NestJS系列】连接数据库及优雅地处理响应

时间:2025-11-04 13:40:46 来源:益强数据堂 作者:应用开发 阅读:548次

前言

Nest作为一个node框架,系列当然也可以连接数据库,连接理响为前端提供CURD接口

我们以mysql为例,数据自行安装mysql

TypeORM

TypeORM 是库及一个ORM框架,它可以运行在 NodeJS、优雅Browser、地处Cordova、系列PhoneGap、连接理响Ionic、数据React Native、库及Expo 和 Electron 平台上,优雅可以与 TypeScript 和 JavaScript一起使用。地处它的系列目标是始终支持最新的 JavaScript 特性并提供额外的特性以帮助你开发任何使用数据库的(不管是只有几张表的小型应用还是拥有多数据库的大型企业应用)应用程序。

TypeORM作为TypeScript中最成熟的连接理响对象关系映射器,可以很好的数据与Nest框架集成使用。

安装依赖

复制npm install --save @nestjs/typeorm typeorm mysql21.

新建数据库

复制CREATE DATABASE nanjiu DEFAULT CHARACTER SET = utf8mb4;1.2.

新建一个nanjiu数据库

图片

连接数据库

数据库建好之后,我们就可以使用typeorm来连接数据库并建立映射关系了

复制// dbConfig.ts // 数据库配置 export function dbConfig() { return { type: mysql, // 数据库类型 host: 127.0.0.1, // 数据库地址 port: 3306, // 端口 username: root, // 用户名 password: 123456, // 密码 database: nanjiu, // 数据库名 entities: [__dirname + /../**/*.entity{.ts,.js}], // 实体类 synchronize: true, // 自动创建表 autoLoadEntities: true, // 自动加载实体类 } as DbConfig }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

需要在app.module.ts中进行注册

复制@Module({ imports: [ NanjiuModule, UserModule, InfoModule, TypeOrmModule.forRoot(dbConfig() as any) ], controllers: [AppController], providers: [AppService], })1.2.3.4.5.6.7.8.

图片

定义实体

实体是云南idc服务商一个映射到数据库表的类,使用@Entity装饰器来定义

复制// user.entry.ts import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; @Entity(user) // 表名 export class User { @PrimaryGeneratedColumn() // 自增主键 id: number; @Column() // 字段 name: string; }1.2.3.4.5.6.7.8.9.10.11.12.

图片

基本实体由列和关系组成,每个实体必须有一个主列。

每个实体都必须在连接配置中注册:

复制entities: [__dirname + /../**/*.entity{.ts,.js}], // 实体类1.

关联实体

实体定义后需要在module中导入并关联

复制@Module({ imports: [TypeOrmModule.forFeature([User])], controllers: [UserController], providers: [UserService] })1.2.3.4.5.

图片

当你做完这一步之后你会发现数据库里已经根据你刚刚定义的实体建好了表

图片

这是因为刚刚数据库配置那里开启了synchronize: true 自动创建表

CURD接口

数据库准备准备工作完成后,我们就可以来写接口了

「在controller控制器中定义接口path」

复制// user.controller.ts import { CreateUserDto } from ./dto/create-user.dto; export class UserController { constructor( private readonly userService: UserService, ) {} @Post(addUser) create(@Body() createUserDto: CreateUserDto) { // 添加用户 return this.userService.add(createUserDto); } }1.2.3.4.5.6.7.8.9.10.11.12.13.

「新建DTO数据验证器」

复制import { Injectable } from "@nestjs/common"; import { IsNotEmpty, IsString } from "class-validator"; // 引入验证器 @Injectable() export class CreateUserDto { @IsString({ message: 用户名必须是字符串}) // 验证是否是字符串 @IsNotEmpty({ message: 用户名不能为空}) // 验证是否为空 name: string; // 用户名 }1.2.3.4.5.6.7.8.

dto一般用来做参数验证

「注册全局DTO验证管道」

复制// main.ts import { ValidationPipe } from @nestjs/common; app.useGlobalPipes(new ValidationPipe()) // 全局验证管道1.2.3.4.

「service逻辑处理,入库操作」

复制// user.service.ts import { Injectable } from @nestjs/common; import { CreateUserDto } from ./dto/create-user.dto; import { User } from ./entities/user.entity; import { InjectRepository } from @nestjs/typeorm; import { Repository } from typeorm; @Injectable() export class UserService { constructor( // 使用 @InjectRepository(User) 注入实数据库实体 @InjectRepository(User) private readonly userRepository: Repository<User> ) {} async add(createUserDto: CreateUserDto) { // 添加用户,更多操作参考 TypeORM 文档 const res = await this.userRepository.save(createUserDto); return res } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.

「调用接口」

图片

「查看数据库」

调用完接口,此时数据库中会新增一条数据

图片

响应结果处理

从上面的响应结果来看并不规范,只是简单的返回了数据库查询结果,并且当系统发生异常错误时,如果我们没有手动处理异常,所有的异常都会进入到nest内置的异常处理层,它返回的信息格式如下:

复制{ "statusCode": 500, "message": "Internal server error" }1.2.3.4.

比如我们往user库中插入相同的name,但name设置了唯一性,免费信息发布网所以这时会抛出错误,如果我们不处理返回给前端就是上面那种信息,这样前端同学看到就会很蒙,根本不知道为啥报错

图片

所以我们要做的就是将响应格式化处理

在nest中,一般是在「service」中处理异常,如果有异常,直接抛出错误,由「过滤器」捕获,统一格式返回,如果成功,service把结果返回,controller直接return结果即可,由「拦截器」捕获,统一格式返回 失败:过滤器统一处理 成功:拦截器统一处理

异常拦截器

为了更加优雅地处理异常,我们可以创建一个异常过滤器,它主要用来捕获作为HttpException类实例的异常。

「异常抛出封装:」

复制// httpStatus.service.ts import { Injectable, HttpException, HttpStatus, NestInterceptor } from @nestjs/common @Injectable() export class HttpStatusError { static fail(error, status = HttpStatus.BAD_REQUEST) { throw new HttpException({statusCode: status, message: 请求失败, error}, status) } }1.2.3.4.5.6.7.8.9.

「抛出异常:」

复制// group.service.ts // ... import { HttpStatusError } from ../utils/httpStatus.service @Injectable() export class GroupService { constructor( @InjectRepository(Group) private groupRepository: Repository<Group>, @InjectRepository(Template) private templateRepository: Repository<Template>, ) {} // todo: 添加分组 async create(createGroupDto: CreateGroupDto) { const data = this.groupRepository.create(createGroupDto); const group = await this.groupRepository.findOne({ where: { name: createGroupDto.name } }); if (group) { return HttpStatusError.fail(该分组已存在); } try { const res = await this.groupRepository.save(data, { reload: true }); return res; } catch (error) { return HttpStatusError.fail(error); } } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

「异常拦截器封装:」

复制import { ArgumentsHost, Catch, ExceptionFilter, HttpException, } from @nestjs/common; @Catch() export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); const request = ctx.getRequest(); const status = exception.getStatus(); const exceptionRes: any = exception.getResponse(); const { error, message } = exceptionRes; const msgLog = { status, message, error, path: request.url, timestamp: new Date().toLocaleString(), }; response.status(status).json(msgLog); } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.

「使用:」

复制app.useGlobalFilters(new HttpExceptionFilter()); // 全局异常过滤器1.

「请求:」

图片

这样报错信息就能够一目了然,简单实用的话可以直接抛出异常就可以,然后在抛出异常的地方给出详细信息。

全局响应拦截器

那成功的响应应该如何优雅地处理呢?

「Interceptor拦截器」

这里我们可以使用Interceptor拦截器,云服务器提供商给成功响应按固定格式返回

复制import { Injectable, HttpException, HttpStatus, NestInterceptor, ExecutionContext,CallHandler } from @nestjs/common import { Observable } from rxjs import { map } from rxjs/operators @Injectable() export class HttpStatusSuccess implements NestInterceptor{ intercept(context: ExecutionContext, next: CallHandler) :Observable<any> { return next.handle().pipe(map(data => { return { statusCode: HttpStatus.OK, message: 请求成功, data } })) } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

「使用:」

复制app.useGlobalInterceptors(new HttpStatusSuccess()); // 全局拦截器请求成功1.

「请求:」

图片

(责任编辑:系统运维)

推荐内容
  • LCD70TX85A(探索全新世界的尖端视觉科技)
  • BSD操作系统使用教程——掌握自由开源的精髓(解析BSD操作系统的特点与使用技巧)
  • iPhone7相较于iPhone6s的优势与差异(性能、摄影和外观方面的重大改进使iPhone7成为首选)
  • iPhone6升级iOS9.3.2的体验(新系统带来的优化和改进)
  • 装机助手(教你如何使用装机助手完成电脑程序的安装和配置)
  • 联想V310i57200性能优越的笔记本电脑评测(一款高性能的商务办公利器,值得期待)