成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

【NestJS系列】連接數據庫及優雅地處理響應

數據庫 其他數據庫
TypeORM 是一個ORM框架,它可以運行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平臺上,可以與 TypeScript 和 JavaScript一起使用。

前言

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 mysql2

新建數據庫

CREATE DATABASE nanjiu
    DEFAULT CHARACTER SET = 'utf8mb4';

新建一個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
}

需要在app.module.ts中進行注冊

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

圖片圖片

定義實體

實體是一個映射到數據庫表的類,使用@Entity裝飾器來定義

// user.entry.ts
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity('user')  // 表名
export class User {

    @PrimaryGeneratedColumn() // 自增主鍵
    id: number;

    @Column() // 字段
    name: string;
}

圖片圖片

基本實體由列和關系組成,每個實體必須有一個主列。

每個實體都必須在連接配置中注冊:

entities: [__dirname + '/../**/*.entity{.ts,.js}'], // 實體類

關聯實體

實體定義后需要在module中導入并關聯

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

圖片圖片

當你做完這一步之后你會發現數據庫里已經根據你剛剛定義的實體建好了表

圖片圖片

這是因為剛剛數據庫配置那里開啟了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);
  }
}

「新建DTO數據驗證器」

import { Injectable } from "@nestjs/common";
import { IsNotEmpty, IsString } from "class-validator"; // 引入驗證器
@Injectable() 
export class CreateUserDto {
    @IsString({ message: '用戶名必須是字符串'}) // 驗證是否是字符串
    @IsNotEmpty({ message: '用戶名不能為空'}) // 驗證是否為空
    name: string; // 用戶名
}

dto一般用來做參數驗證

「注冊全局DTO驗證管道」

// main.ts
import { ValidationPipe } from '@nestjs/common';

app.useGlobalPipes(new ValidationPipe()) // 全局驗證管道

「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
  }
}

「調用接口」

圖片圖片

「查看數據庫」

調用完接口,此時數據庫中會新增一條數據

圖片圖片

響應結果處理

從上面的響應結果來看并不規范,只是簡單的返回了數據庫查詢結果,并且當系統發生異常錯誤時,如果我們沒有手動處理異常,所有的異常都會進入到nest內置的異常處理層,它返回的信息格式如下:

{
  "statusCode": 500,
  "message": "Internal server error"
}

比如我們往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)
    }
}

「拋出異常:」

// 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);
    }
  }
}

「異常攔截器封裝:」

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);
    }
  }

「使用:」

app.useGlobalFilters(new HttpExceptionFilter()); // 全局異常過濾器

「請求:」

圖片圖片

這樣報錯信息就能夠一目了然,簡單實用的話可以直接拋出異常就可以,然后在拋出異常的地方給出詳細信息。

全局響應攔截器

那成功的響應應該如何優雅地處理呢?

「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
            }
        }))
    }
}

「使用:」

app.useGlobalInterceptors(new HttpStatusSuccess()); // 全局攔截器請求成功

「請求:」

圖片 圖片

責任編輯:武曉燕 來源: 前端南玖
相關推薦

2009-07-20 15:14:44

iBATIS.NET連

2014-07-22 09:01:53

SwiftJSON

2009-07-06 17:23:34

JDBC連接數據庫

2011-03-16 17:14:17

JavaBean數據庫

2025-01-20 07:10:00

LambdaJavanull

2009-08-25 16:01:32

C#.NET連接數據庫

2020-11-23 14:16:42

Golang

2009-07-20 15:56:08

JDBC連接數據庫步驟

2010-08-04 10:32:56

Flex連接數據庫

2009-07-14 17:18:23

JDBC怎么連接數據庫

2009-08-25 14:05:06

C#連接數據庫代碼

2009-03-19 10:08:09

C#數據庫查詢

2011-07-05 09:54:04

2010-10-12 12:00:42

MySQL連接

2023-05-12 12:09:38

職責鏈模式客服

2009-06-30 14:59:36

連接數據庫JSP入門

2009-08-05 15:40:49

ASP.NET連接數據

2009-07-17 15:34:37

Java Swing連接數據庫

2009-07-20 14:30:38

jdbc連接數據庫代碼

2009-12-23 09:40:53

ADO對象模型
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天色天天 | 美女视频黄的 | 久久专区 | 国产1区 | 一二三四在线视频观看社区 | 成人乱人乱一区二区三区软件 | 在线观看日本网站 | 国产视频中文字幕 | 91成人精品| 亚洲国产伊人 | 91精品欧美久久久久久久 | 国产成人久久精品一区二区三区 | 久久伊人精品 | 中文字幕一区二区三区日韩精品 | 国产欧美日韩一区二区三区在线 | 中文字幕免费在线 | 成av在线 | 国产精品欧美一区二区三区 | 盗摄精品av一区二区三区 | 亚洲欧美在线观看 | 欧美xxxx性xxxxx高清 | 日韩中文一区二区 | 国产成人免费视频网站高清观看视频 | 国产精品久久久久久久久久免费看 | 国产精品免费一区二区三区四区 | 国产一区二区影院 | 久久久www成人免费无遮挡大片 | 国产成人网 | 欧美亚洲视频 | 亚洲国产成人精品女人久久久 | www.日本三级 | 91精品欧美久久久久久久 | 国产91久久久久久 | 国产午夜精品一区二区三区在线观看 | 亚洲在线一区 | 人人做人人澡人人爽欧美 | 看一级黄色毛片 | 国产精品亚洲片在线播放 | 请别相信他免费喜剧电影在线观看 | 免费成人国产 | 国产福利在线免费观看 |