自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

【NestJS系列】連接數(shù)據(jù)庫及優(yōu)雅地處理響應(yīng)

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

前言

Nest作為一個node框架,當(dāng)然也可以連接數(shù)據(jù)庫,為前端提供CURD接口

我們以mysql為例,自行安裝mysql

TypeORM

TypeORM 是一個ORM框架,它可以運(yùn)行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平臺上,可以與 TypeScript 和 JavaScript一起使用。它的目標(biāo)是始終支持最新的 JavaScript 特性并提供額外的特性以幫助你開發(fā)任何使用數(shù)據(jù)庫的(不管是只有幾張表的小型應(yīng)用還是擁有多數(shù)據(jù)庫的大型企業(yè)應(yīng)用)應(yīng)用程序。

TypeORM作為TypeScript中最成熟的對象關(guān)系映射器,可以很好的與Nest框架集成使用。

安裝依賴

npm install --save @nestjs/typeorm typeorm mysql2

新建數(shù)據(jù)庫

CREATE DATABASE nanjiu
    DEFAULT CHARACTER SET = 'utf8mb4';

新建一個nanjiu數(shù)據(jù)庫

圖片圖片

連接數(shù)據(jù)庫

數(shù)據(jù)庫建好之后,我們就可以使用typeorm來連接數(shù)據(jù)庫并建立映射關(guān)系了

// dbConfig.ts
// 數(shù)據(jù)庫配置
export function dbConfig()  {
    return {
        type: 'mysql', // 數(shù)據(jù)庫類型
        host: '127.0.0.1', // 數(shù)據(jù)庫地址
        port: 3306, // 端口
        username: 'root', // 用戶名
        password: '123456', // 密碼
        database: 'nanjiu', // 數(shù)據(jù)庫名
        entities: [__dirname + '/../**/*.entity{.ts,.js}'], // 實(shí)體類
        synchronize: true, // 自動創(chuàng)建表
        autoLoadEntities: true, // 自動加載實(shí)體類
    } as DbConfig
}

需要在app.module.ts中進(jìn)行注冊

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

圖片圖片

定義實(shí)體

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

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

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

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

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

圖片圖片

基本實(shí)體由列和關(guān)系組成,每個實(shí)體必須有一個主列。

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

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

關(guān)聯(lián)實(shí)體

實(shí)體定義后需要在module中導(dǎo)入并關(guān)聯(lián)

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

圖片圖片

當(dāng)你做完這一步之后你會發(fā)現(xiàn)數(shù)據(jù)庫里已經(jīng)根據(jù)你剛剛定義的實(shí)體建好了表

圖片圖片

這是因?yàn)閯倓倲?shù)據(jù)庫配置那里開啟了synchronize: true 自動創(chuàng)建表

CURD接口

數(shù)據(jù)庫準(zhǔn)備準(zhǔn)備工作完成后,我們就可以來寫接口了

「在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數(shù)據(jù)驗(yàn)證器」

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

dto一般用來做參數(shù)驗(yàn)證

「注冊全局DTO驗(yàn)證管道」

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

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

「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) 注入實(shí)數(shù)據(jù)庫實(shí)體
    @InjectRepository(User)
    private readonly userRepository: Repository<User>
  ) {}

 async add(createUserDto: CreateUserDto) {
    // 添加用戶,更多操作參考 TypeORM 文檔
    const res = await this.userRepository.save(createUserDto);
    return res
  }
}

「調(diào)用接口」

圖片圖片

「查看數(shù)據(jù)庫」

調(diào)用完接口,此時數(shù)據(jù)庫中會新增一條數(shù)據(jù)

圖片圖片

響應(yīng)結(jié)果處理

從上面的響應(yīng)結(jié)果來看并不規(guī)范,只是簡單的返回了數(shù)據(jù)庫查詢結(jié)果,并且當(dāng)系統(tǒng)發(fā)生異常錯誤時,如果我們沒有手動處理異常,所有的異常都會進(jìn)入到nest內(nèi)置的異常處理層,它返回的信息格式如下:

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

比如我們往user庫中插入相同的name,但name設(shè)置了唯一性,所以這時會拋出錯誤,如果我們不處理返回給前端就是上面那種信息,這樣前端同學(xué)看到就會很蒙,根本不知道為啥報錯

圖片圖片

所以我們要做的就是將響應(yīng)格式化處理

在nest中,一般是在「service」中處理異常,如果有異常,直接拋出錯誤,由「過濾器」捕獲,統(tǒng)一格式返回,如果成功,service把結(jié)果返回,controller直接return結(jié)果即可,由「攔截器」捕獲,統(tǒng)一格式返回 失?。哼^濾器統(tǒng)一處理 成功:攔截器統(tǒng)一處理

異常攔截器

為了更加優(yōu)雅地處理異常,我們可以創(chuàng)建一個異常過濾器,它主要用來捕獲作為HttpException類實(shí)例的異常。

「異常拋出封裝:」

// 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()); // 全局異常過濾器

「請求:」

圖片圖片

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

全局響應(yīng)攔截器

那成功的響應(yīng)應(yīng)該如何優(yōu)雅地處理呢?

「Interceptor攔截器」

這里我們可以使用Interceptor攔截器,給成功響應(yīng)按固定格式返回

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()); // 全局?jǐn)r截器請求成功

「請求:」

圖片 圖片

責(zé)任編輯:武曉燕 來源: 前端南玖
相關(guān)推薦

2009-07-20 15:14:44

iBATIS.NET連

2014-07-22 09:01:53

SwiftJSON

2009-07-06 17:23:34

JDBC連接數(shù)據(jù)庫

2011-03-16 17:14:17

JavaBean數(shù)據(jù)庫

2025-01-20 07:10:00

LambdaJavanull

2009-03-19 10:08:09

C#數(shù)據(jù)庫查詢

2009-08-25 16:01:32

C#.NET連接數(shù)據(jù)庫

2020-11-23 14:16:42

Golang

2010-10-12 12:00:42

MySQL連接

2011-07-05 09:54:04

2009-08-25 14:05:06

C#連接數(shù)據(jù)庫代碼

2009-07-14 17:18:23

JDBC怎么連接數(shù)據(jù)庫

2009-07-20 15:56:08

JDBC連接數(shù)據(jù)庫步驟

2010-08-04 10:32:56

Flex連接數(shù)據(jù)庫

2023-05-12 12:09:38

職責(zé)鏈模式客服

2009-06-15 15:26:00

NetBeans連接數(shù)使用JSTL

2009-09-04 17:49:34

C#連接數(shù)據(jù)庫

2009-07-20 14:30:38

jdbc連接數(shù)據(jù)庫代碼

2009-06-30 14:59:36

連接數(shù)據(jù)庫JSP入門

2009-12-23 09:40:53

ADO對象模型
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號