当前位置:科技动态 > 【NestJS系列】连接数据库并优雅地处理响应

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

  • 发布:2023-10-01 16:59

前言

Node 作为后端语言,当然也可以连接数据库,并为前端提供 CURD 接口

我们以mysql为例安装mysql

类型ORM

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自动创建表

CURD接口

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

定义控制器控制器中的接口路径

// 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(模板)
    私有模板存储库:存储库