NestJS 3 分钟搭好 MySQL + MongoDB,CRUD 复制粘贴直接运行

基于上一篇内容《为什么现代 Node 后端都选 NestJS + TypeScript?这组合真香了》,这篇文章继续写数据库的连接。

所以今天把MySQL、MongoDB 全接上,做个小实例。朋友们项目里用什么数据库可以视情况而定。

这里的功能分别为:

  • MySQL:存用户
  • MongoDB:存日志

代码短、跟着敲就行。

1. 生成对应架构

执行以下命令生成相关模块代码(Module/Service/Controller)

bash 复制代码
nest g res user
nest g res log

2. 装包

bash 复制代码
pnpm i @nestjs/typeorm typeorm mysql2
pnpm i @nestjs/mongoose mongoose

3. 连库

app.module.ts 一次配好

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: [
    // MySQL
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'SV^u8@rB8',
      database: 'demo',
      autoLoadEntities: true,
      synchronize: true, // 仅本地用,生产关掉
    }),

    // MongoDB
    MongooseModule.forRoot('mongodb://localhost:27017/test'),

    // 业务模块
    TodoModule,

    UserModule,

    LogModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

代码生成了,接下来我们来处理数据库和增删改查的代码。

Mysql

1. 实体和数据表

数据库表
sql 复制代码
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 实体
ts 复制代码
// user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn() id: number;
  @Column() name: string;
  @Column() age: number;
}
Dto
ts 复制代码
// create-user.dto.ts
export class CreateUserDto {
  name: string;
  age: number;
}

这里容易出现一个Eslint问题的爆红,如下图:

出现这种情况执行以下命令:

bash 复制代码
npx eslint "src/**/*.{ts,js}" --fix --ext .ts,.js

如果还是不行,再执行下这个

bash 复制代码
npx prettier --write "src/**/*.{ts,js,json}"

2. 业务代码(cv即可)

user.controller.ts
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

ts 复制代码
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

完成了增删改查的业务代码

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. 跑起来,测试下接口

bash 复制代码
npm run start

新增

POST http://localhost:3000/user

json 复制代码
{ "name": "张三", "age": 30 }

修改

POST http://localhost:3000/user

json 复制代码
{ "id": 1, "name": "张三", "age": 31 }

删除

DELETE http://localhost:3000/user/1

查询

GET http://localhost:3000/user/1

这里实现mysql的增删改查就完成了

MongoDB

大致流程和mysql是一样的,写法稍微有些差别

1. 实体和集合

创建一个集合
sql 复制代码
db.createCollection("logs");
集合 实体
ts 复制代码
// 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
ts 复制代码
// create-log.dto.ts
export class CreateLogDto {
  message: string;
  timestamp?: Date;
}

2. 业务代码(cv即可)

log.controller.ts
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

ts 复制代码
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

增删改查的业务代码

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. 启动,测试接口

bash 复制代码
npm run start

新增

POST http://localhost:3000/log

json 复制代码
{ "message": "张三的消息" }

修改

POST http://localhost:3000/log

json 复制代码
{ "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个真实场景让你代码更优雅》

相关推荐
jiayou641 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
于眠牧北1 天前
MySQL的锁类型,表锁,行锁,MVCC中所使用的临键锁
mysql
李广坤2 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
Turnip12023 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
爱可生开源社区3 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
AI全栈实验室3 天前
MongoDB迁移金仓踩了5个坑,最后一个差点回滚
mongodb
随逸1773 天前
《从零搭建NestJS项目》
数据库·typescript
加号34 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏4 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐4 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端