基于上一篇內容《為什么現代 Node 后端都選 NestJS + TypeScript?這組合真香了》,這篇文章繼續寫數據庫的連接。
所以今天把MySQL、MongoDB全接上,做個小實例。朋友們項目里用什么數據庫可以視情況而定。
這里的功能分別為:
- MySQL:存用戶
- MongoDB:存日志
代碼短、跟著敲就行。
1. 生成對應架構
執行以下命令生成相關模塊代碼(Module/Service/Controller)
nest g res user
nest g res log
2. 裝包
pnpm i @nestjs/typeorm typeorm mysql2
pnpm i @nestjs/mongoose mongoose
3. 連庫
在app.module.ts
一次配好
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TodoModule } from './todo/todo.module';
import { UserModule } from './user/user.module';
import { LogModule } from './log/log.module';@Module({imports: [// MySQLTypeOrmModule.forRoot({type: 'mysql',host: 'localhost',port: 3306,username: 'root',password: 'SV^u8@rB8',database: 'demo',autoLoadEntities: true,synchronize: true, // 僅本地用,生產關掉}),// MongoDBMongooseModule.forRoot('mongodb://localhost:27017/test'),// 業務模塊TodoModule,UserModule,LogModule,],controllers: [AppController],providers: [AppService],
})
export class AppModule {}
代碼生成了,接下來我們來處理數據庫和增刪改查的代碼。
Mysql
1. 實體和數據表
數據庫表
CREATE TABLE `user` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主鍵',`name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用戶名',`age` int DEFAULT NULL COMMENT '年齡',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用戶表';
MySQL 實體
// user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';@Entity()
export class User {@PrimaryGeneratedColumn() id: number;@Column() name: string;@Column() age: number;
}
Dto
// create-user.dto.ts
export class CreateUserDto {name: string;age: number;
}
這里容易出現一個Eslint
問題的爆紅,如下圖:
出現這種情況執行以下命令:
npx eslint "src/**/*.{ts,js}" --fix --ext .ts,.js
如果還是不行,再執行下這個
npx prettier --write "src/**/*.{ts,js,json}"
2. 業務代碼(cv即可)
user.controller.ts
import { Controller, Get, Post, Body, Patch, Param, Delete,} from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';@Controller('user')
export class UserController {constructor(private readonly userService: UserService) {}@Post()create(@Body() createUserDto: CreateUserDto) {return this.userService.create(createUserDto);}@Get()findAll() {return this.userService.findAll();}@Get(':id')findOne(@Param('id') id: string) {return this.userService.findOne(+id);}@Patch(':id')update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {return this.userService.update(+id, updateUserDto);}@Delete(':id')remove(@Param('id') id: string) {return this.userService.remove(+id);}
}
user.module.ts
這里稍微的修改了一下,引入了TypeOrmModule
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { User } from './entities/user.entity';@Module({imports: [TypeOrmModule.forFeature([User])],controllers: [UserController],providers: [UserService],
})
export class UserModule {}
user.service.ts
完成了增刪改查的業務代碼
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { User } from './entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';@Injectable()
export class UserService {constructor(@InjectRepository(User)private readonly repo: Repository<User>,) {}async create(createUserDto: CreateUserDto): Promise<User> {return await this.repo.save(createUserDto);}async findAll(): Promise<User[]> {return await this.repo.find();}async findOne(id: number): Promise<User> {const user = await this.repo.findOne({ where: { id } });if (!user) {throw new Error(`User with ID ${id} not found`);}return user;}async update(id: number, updateUserDto: UpdateUserDto): Promise<User> {const user = await this.findOne(id);Object.assign(user, updateUserDto);return await this.repo.save(user);}async remove(id: number): Promise<void> {const user = await this.findOne(id);await this.repo.remove(user);}
}
3. 跑起來,測試下接口
npm run start
新增
POST
http://localhost:3000/user
{ "name": "張三", "age": 30 }
修改
POST
http://localhost:3000/user
{ "id": 1, "name": "張三", "age": 31 }
刪除
DELETE
http://localhost:3000/user/1
查詢
GET
http://localhost:3000/user/1
這里實現mysql的增刪改查就完成了
MongoDB
大致流程和mysql是一樣的,寫法稍微有些差別
1. 實體和集合
創建一個集合
db.createCollection("logs");
集合 實體
// log.entity.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';export type LogDocument = Log & Document;@Schema()
export class Log {_id?: Types.ObjectId;@Prop({ required: true })message: string;@Prop({ default: Date.now })timestamp: Date;
}export const LogSchema = SchemaFactory.createForClass(Log);
Dto
// create-log.dto.ts
export class CreateLogDto {message: string;timestamp?: Date;
}
2. 業務代碼(cv即可)
log.controller.ts
import {Controller, Get, Post, Body, Patch, Param, Delete} from '@nestjs/common';
import { LogService } from './log.service';
import { CreateLogDto } from './dto/create-log.dto';
import { UpdateLogDto } from './dto/update-log.dto';@Controller('log')
export class LogController {constructor(private readonly logService: LogService) {}@Post()create(@Body() createLogDto: CreateLogDto) {return this.logService.create(createLogDto);}@Get()findAll() {return this.logService.findAll();}@Get(':id')findOne(@Param('id') id: string) {return this.logService.findOne(id);}@Patch(':id')update(@Param('id') id: string, @Body() updateLogDto: UpdateLogDto) {return this.logService.update(id, updateLogDto);}@Delete(':id')remove(@Param('id') id: string) {return this.logService.remove(id);}
}
log.module.ts
引入了MongooseModule
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { LogService } from './log.service';
import { LogController } from './log.controller';
import { Log, LogSchema } from './entities/log.entity';@Module({imports: [MongooseModule.forFeature([{ name: Log.name, schema: LogSchema }])],controllers: [LogController],providers: [LogService],
})
export class LogModule {}
user.service.ts
增刪改查的業務代碼
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { CreateLogDto } from './dto/create-log.dto';
import { UpdateLogDto } from './dto/update-log.dto';
import { Log, LogDocument } from './entities/log.entity';@Injectable()
export class LogService {constructor(@InjectModel(Log.name) private logModel: Model<LogDocument>) {}async create(createLogDto: CreateLogDto): Promise<Log> {const createdLog = new this.logModel(createLogDto);return createdLog.save();}async findAll(): Promise<Log[]> {return this.logModel.find().exec();}async findOne(id: string): Promise<Log> {const log = await this.logModel.findById(id).exec();if (!log) {throw new Error(`Log with ID ${id} not found`);}return log;}async update(id: string, updateLogDto: UpdateLogDto): Promise<Log> {const updatedLog = await this.logModel.findByIdAndUpdate(id, updateLogDto, { new: true }).exec();if (!updatedLog) {throw new Error(`Log with ID ${id} not found`);}return updatedLog;}async remove(id: string): Promise<void> {const result = await this.logModel.findByIdAndDelete(id).exec();if (!result) {throw new Error(`Log with ID ${id} not found`);}}
}
3. 啟動,測試接口
npm run start
新增
POST
http://localhost:3000/log
{ "message": "張三的消息" }
修改
POST
http://localhost:3000/log
{ "id": 1, "message": "李四的消息"}
刪除
DELETE
http://localhost:3000/log/1
查詢
GET
http://localhost:3000/log/1
MongoDB
的增刪改查完成
小結
- MySQL:使用
TypeORM
實體一把梭 - MongoDB:使用
Schema
裝飾器直接上
NestJS真的是結構清晰,開發很快,再也不用從頭造輪子了。
我是大華,專注分享前后端開發的實戰筆記。關注我,少走彎路,一起進步!
📌往期精彩
《Elasticsearch 太重?來看看這個輕量級的替代品 Manticore Search》
《別再if套if了!Java中return的9種優雅寫法》
《別學23種了!Java項目中最常用的6個設計模式,附案例》
《寫給小公司前端的 UI 規范:別讓頁面丑得自己都看不下去》
《Vue3+TS設計模式:5個真實場景讓你代碼更優雅》