NestJS 搭建博客系统(三)— 使用TypeORM+Mysql实现数据持久化
前言
这一节我们使用 TypeORM + Mysql 实现数据持久化。
TypeORM 是一个 ORM 框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,可以与 TypeScript 和 JavaScript (ES5,ES6,ES7,ES8)一起使用。 它的目标是始终支持最新的 JavaScript 特性并提供额外的特性以帮助你开发任何使用数据库的(不管是只有几张表的小型应用还是拥有多数据库的大型企业应用)应用程序。
你也可以选择 Squelize ORM
环境配置
安装 Mysql
这里我不详细展开 Mysql 的安装方法。顺便安利个简便的配置方式,同时也是我正在使用的方式。使用 docker 运行 mysql。 github.com/huihuipan/e… 这个库里面配置了 Mysql、Mongodb、Redis、nginx、jenkins、yapi 等服务,可以根据自己需要选择自己的服务。
软件部分
软件会用到数据库工具,如 navicat / dbeaver 调试请求会用到 postman 或者也可以使用上面的 environment 里面提供的 yapi
编写代码
安装依赖
使用 TypeORM 和 mysql 需要在项目中安装以下包
npm install --save @nestjs/typeorm typeorm mysql2 复制代码
引用配置
首先我们在 app.module 中引用 TypeOrmModule,TypeOrmModule 由 @nestjs/typeorm 提供
// src/app.modules.ts import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { ArticleModule } from './modules/article/article.module'; import { TypeOrmModule } from '@nestjs/typeorm' @Module({ imports: [ // 使用 TypeORM 配置数据库 TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: '888888', database: 'test', entities: ["dist/modules/**/*.entity{.ts,.js}"], synchronize: true, }), ArticleModule ], controllers: [AppController], providers: [AppService], }) export class AppModule {} 复制代码
创建实体 Entity
Entity 是由 @Entity 装饰器装饰的模型。 TypeORM 会为此类模型创建数据库表。
新建文件 src/modules/article/entity/article.entity.ts
// src/modules/article/entity/article.entity.ts import { Entity, Column, PrimaryGeneratedColumn, UpdateDateColumn, CreateDateColumn, VersionColumn, } from 'typeorm'; @Entity() export class Article { // 主键id @PrimaryGeneratedColumn() id: number; // 创建时间 @CreateDateColumn() createTime: Date // 更新时间 @UpdateDateColumn() updateTime: Date // 软删除 @Column({ default: false }) isDelete: boolean // 更新次数 @VersionColumn() version: number // 文章标题 @Column('text') title: string; // 文章描述 @Column('text') description: string; // 文章内容 @Column('text') content: string; } 复制代码
使用 DTO
关于 DTO,NestJS 是这么说的
DTO(数据传输对象)模式。DTO是一个对象,它定义了如何通过网络发送数据。我们可以通过使用 TypeScript 接口(Interface)或简单的类(Class)来定义 DTO 模式。有趣的是,我们在这里推荐使用类。为什么?类是 JavaScript ES6 标准的一部分,因此它们在编译后的 JavaScript 中被保留为实际实体。另一方面,由于 TypeScript 接口在转换过程中被删除,所以 Nest 不能在运行时引用它们。这一点很重要,因为诸如管道(Pipe)之类的特性为在运行时访问变量的元类型提供更多的可能性。
在 java 里面
DTO: 数据传输对象,原先是为分布式提供粗粒度的数据实体,减少调用次数来提升性能和降低网络压力。
简单来说,就是定义一个数据,作用类似于定义方法的入参,而且还能方便我们做其他事情。比如我们的表单验证就可以在 DTO 中使用。
创建以下文件
// src/modules/article/dto/list.dto.ts export class ListDTO { readonly page: number; readonly pageSize: number; } 复制代码
// src/modules/article/dto/id.dto.ts export class IdDTO { readonly id: number } 复制代码
// src/modules/article/dto/article-create.dto.ts export class ArticleCreateDTO { readonly title: string; readonly description: string; readonly content: string; } 复制代码
// src/modules/article/dto/article-edit.dto.ts export class ArticleEditDTO { readonly id: number; readonly title: string; readonly description: string; readonly content: string; } 复制代码
控制器中使用 DTO
import { Controller, Body, Query, Get, Post, } from '@nestjs/common'; import { ArticleService } from './article.service'; import { ArticleCreateDTO } from './dto/article-create.dto'; import { ArticleEditDTO } from './dto/article-edit.dto'; import { IdDTO } from './dto/id.dto'; import { ListDTO } from './dto/list.dto'; @Controller('article') export class ArticleController { constructor( private articleService: ArticleService ) {} @Get('list') getMore( @Query() listDTO: ListDTO, ) { return this.articleService.getMore(listDTO) } @Get('info') getOne( @Query() idDto: IdDTO ) { return this.articleService.getOne(idDto) } @Post('create') create( @Body() articleCreateDTO: ArticleCreateDTO ) { return this.articleService.create(articleCreateDTO) } @Post('edit') update( @Body() articleEditDTO: ArticleEditDTO ) { return this.articleService.update(articleEditDTO) } @Post('delete') delete( @Body() idDto: IdDTO, ) { return this.articleService.delete(idDto) } } 复制代码
在 article.module 中定义使用那些存储库
import { Module } from '@nestjs/common'; import { ArticleService } from './article.service'; import { ArticleController } from './article.controller'; import { Article } from './entity/article.entity'; import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ TypeOrmModule.forFeature([Article]), ], providers: [ArticleService], controllers: [ArticleController] }) export class ArticleModule {} 复制代码
同时修改下我们的服务,改为使用 TypeORM 存取数据
import { Injectable } from '@nestjs/common'; import { ArticleCreateDTO } from './dto/article-create.dto'; import { ArticleEditDTO } from './dto/article-edit.dto'; import { IdDTO } from './dto/id.dto'; import { ListDTO } from './dto/list.dto'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Article } from './entity/article.entity'; @Injectable() export class ArticleService { list: any[]; constructor( @InjectRepository(Article) private readonly articleRepository: Repository<Article>, ) { this.list = [] } async getMore( listDTO: ListDTO, ) { const { page = 1, pageSize = 10 } = listDTO const getList = this.articleRepository .createQueryBuilder('article') .where({ isDelete: false }) .select([ 'article.id', 'article.title', 'article.description', 'article.createTime', 'article.updateTime', ]) .skip((page - 1) * pageSize) .take(pageSize) .getMany() const list = await getList return list } async getOne( idDto: IdDTO ) { const { id } = idDto const articleDetial = await this.articleRepository .createQueryBuilder('article') .where('article.id = :id', { id }) .getOne() return articleDetial; } async create( articleCreateDTO: ArticleCreateDTO ):Promise<Article>{ const article = new Article(); article.title = articleCreateDTO.title article.description = articleCreateDTO.description article.content = articleCreateDTO.content const result = await this.articleRepository.save(article); return result } async update( articleEditDTO: ArticleEditDTO ): Promise<Article>{ const { id } = articleEditDTO let articleToUpdate = await this.articleRepository.findOne({ id }) articleToUpdate.title = articleEditDTO.title articleToUpdate.description = articleEditDTO.description articleToUpdate.content = articleEditDTO.content const result = await this.articleRepository.save(articleToUpdate) return result } async delete ( idDTO: IdDTO, ) { const { id } = idDTO let articleToUpdate = await this.articleRepository.findOne({ id }) articleToUpdate.isDelete = true const result = await this.articleRepository.save(articleToUpdate) return result } }
作者:斯蒂芬大狗
链接:https://juejin.cn/post/6992097780487929870