news 2026/6/15 12:47:59

NestJS 项目 - 快速生成 CRUD

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NestJS 项目 - 快速生成 CRUD
CREATE TABLE `sys_banner` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `image` varchar(255) DEFAULT NULL COMMENT '图片地址', `url` varchar(255) DEFAULT NULL COMMENT '跳转地址', `sort` int(1) DEFAULT '0' COMMENT '排序', `status` int(1) DEFAULT '1' COMMENT '状态 0=下架, 1=上架', `tenant_id` int(11) DEFAULT NULL COMMENT '租户ID', `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', `creator` varchar(64) DEFAULT NULL COMMENT '创建者', `updater` varchar(64) DEFAULT NULL COMMENT '更新者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='轮播图';

1. 创建模块结构

使用 Nest CLI 快速生成 Banner 表模块:

命令行执行: nest g res banner

PS D:\Java\work\nodejs-demo\nest-admin> cd .\server\src\module\system\ PS D:\Java\work\nodejs-demo\nest-admin\server\src\module\system> nest g res banner ✔ What transport layer do you use? REST API ? Would you like to generate CRUD entry points? (Y/n) (按回车生成)

按Enter回车

PS D:\Java\work\nodejs-demo\nest-admin> cd .\server\src\module\system\ PS D:\Java\work\nodejs-demo\nest-admin\server\src\module\system> nest g res banner ✔ What transport layer do you use? REST API ✔ Would you like to generate CRUD entry points? Yes CREATE banner/banner.controller.ts (959 bytes) CREATE banner/banner.controller.spec.ts (596 bytes) CREATE banner/banner.module.ts (264 bytes) CREATE banner/banner.service.ts (661 bytes) CREATE banner/banner.service.spec.ts (478 bytes) CREATE banner/dto/create-banner.dto.ts (33 bytes) CREATE banner/dto/update-banner.dto.ts (181 bytes) CREATE banner/entities/banner.entity.ts (24 bytes) UPDATE system.module.ts (965 bytes) PS D:\Java\work\nodejs-demo\nest-admin\server\src\module\system>

选择配置:

  • Transport layer:REST API

  • Generate CRUD entry points:Yes

2. 生成的文件结构

banner/ ├── banner.controller.ts # 控制器 ├── banner.service.ts # 服务层 ├── banner.module.ts # 模块配置 ├── entities/ │ └── banner.entity.ts # 实体类 └── dto/ ├── create-banner.dto.ts # 创建 DTO └── update-banner.dto.ts # 更新 DTO

spec是测试类, 可忽略

3. 配置数据库实体

修改banner.entity.ts,映射数据库表:

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity('sys_banner') export class Banner { @PrimaryGeneratedColumn() id: number; @Column({ length: 255, nullable: true, comment: '图片地址' }) image: string; @Column({ length: 255, nullable: true, comment: '跳转地址' }) url: string; @Column({ default: 0, comment: '排序' }) sort: number; @Column({ default: 1, comment: '状态 0=下架, 1=上架' }) status: number; @Column({ nullable: true, comment: '租户ID' }) tenant_id: number; @Column({ default: false, comment: '是否删除' }) deleted: boolean; @Column({ length: 64, nullable: true, comment: '创建者' }) creator: string; @Column({ length: 64, nullable: true, comment: '更新者' }) updater: string; @Column({ type: 'datetime', nullable: true, comment: '创建时间' }) create_time: Date; @Column({ type: 'datetime', nullable: true, comment: '更新时间' }) update_time: Date; }

4. 配置 DTO 数据验证

create-banner.dto.ts

import { IsString, IsOptional, IsInt, IsBoolean, IsUrl } from 'class-validator'; export class CreateBannerDto { @IsString() image: string; @IsOptional() @IsUrl() url?: string; @IsOptional() @IsInt() sort?: number; @IsOptional() @IsInt() status?: number; @IsOptional() @IsInt() tenant_id?: number; }

update-banner.dto.ts

已经继承CreateBannerDto

import { PartialType } from '@nestjs/mapped-types'; import { CreateBannerDto } from './create-banner.dto'; export class UpdateBannerDto extends PartialType(CreateBannerDto) {}

5. 服务层逻辑

banner.service.ts核心方法:

import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Banner } from './entities/banner.entity'; import { CreateBannerDto } from './dto/create-banner.dto'; import { UpdateBannerDto } from './dto/update-banner.dto'; @Injectable() export class BannerService { constructor( @InjectRepository(Banner) private bannerRepository: Repository<Banner>, ) {} create(createBannerDto: CreateBannerDto) { return this.bannerRepository.save(createBannerDto); } findAll() { return this.bannerRepository.find({ where: { deleted: false }, order: { sort: 'ASC' } }); } findOne(id: number) { return this.bannerRepository.findOneBy({ id, deleted: false }); } update(id: number, updateBannerDto: UpdateBannerDto) { return this.bannerRepository.update(id, { ...updateBannerDto, update_time: new Date() }); } remove(id: number) { // 软删除 return this.bannerRepository.update(id, { deleted: true, update_time: new Date() }); } }

6. 控制器路由

banner.controller.ts

import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; import { BannerService } from './banner.service'; import { CreateBannerDto } from './dto/create-banner.dto'; import { UpdateBannerDto } from './dto/update-banner.dto'; @Controller('banner') export class BannerController { constructor(private readonly bannerService: BannerService) {} @Post() create(@Body() createBannerDto: CreateBannerDto) { return this.bannerService.create(createBannerDto); } @Get() findAll() { return this.bannerService.findAll(); } @Get(':id') findOne(@Param('id') id: string) { return this.bannerService.findOne(+id); } @Patch(':id') update(@Param('id') id: string, @Body() updateBannerDto: UpdateBannerDto) { return this.bannerService.update(+id, updateBannerDto); } @Delete(':id') remove(@Param('id') id: string) { return this.bannerService.remove(+id); } }

7. 模块配置

banner.module.ts

import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { BannerService } from './banner.service'; import { BannerController } from './banner.controller'; import { Banner } from './entities/banner.entity'; @Module({ imports: [TypeOrmModule.forFeature([Banner])], controllers: [BannerController], providers: [BannerService], }) export class BannerModule {}

8. 自动注册到 SystemModule

Nest CLI 会自动更新system.module.ts

import { Module } from '@nestjs/common'; import { BannerModule } from './banner/banner.module'; @Module({ imports: [BannerModule], // 自动添加 }) export class SystemModule {}

9. 接口测试

生成的 REST API:

GET /banner # 获取所有轮播图 GET /banner/:id # 获取单个轮播图 POST /banner # 创建轮播图 PATCH /banner/:id # 更新轮播图 DELETE /banner/:id # 删除轮播图(软删除)

总结

通过nest g res命令可以快速生成标准的 CRUD 模块,包含:

  • 完整的 REST API 接口

  • TypeORM 实体映射

  • 基本的 DTO 验证

  • 模块化的代码结构

后续可根据业务需求添加:

  • 权限控制(@Roles() 装饰器)

  • 数据验证管道

  • 日志记录

  • 缓存机制

  • 文件上传处理

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/13 22:28:25

MFC实现文件监控与FTP上传

在vc6.0 mfc 环境下新建工程名称FileMonitor 的MFC Appwizard(exe) 对话框&#xff0c;添加一个启动监控按钮&#xff0c;一个关闭监控按钮。ftp服务器ip 192.168.3.100 匿名身份验证物理路径 d:\FTPRoot 被监控电脑上被监控文件夹是d:\1。点击启动监控按钮时&#xff0c;当被…

作者头像 李华
网站建设 2026/6/12 18:30:32

动态线程池技术深度解析:构建高性能可观测的线程管理方案

技术背景与核心痛点 【免费下载链接】dynamic-tp &#x1f525;&#x1f525;&#x1f525;轻量级动态线程池&#xff0c;内置监控告警功能&#xff0c;集成三方中间件线程池管理&#xff0c;基于主流配置中心&#xff08;已支持Nacos、Apollo&#xff0c;Zookeeper、Consul、E…

作者头像 李华
网站建设 2026/6/10 15:52:24

完整示例演示修复Multisim主数据库拒绝访问问题

修复Multisim主数据库拒绝访问&#xff1a;从权限冲突到自动化恢复的实战指南你有没有遇到过这样的场景&#xff1f;早上打开电脑&#xff0c;准备继续昨天没完成的电路仿真&#xff0c;双击启动 Multisim&#xff0c;结果弹出一个冰冷的提示&#xff1a;Database access denie…

作者头像 李华
网站建设 2026/6/10 15:58:48

PyTorch-CUDA-v2.6镜像是否可用于边缘设备部署?视硬件而定

PyTorch-CUDA-v2.6镜像是否可用于边缘设备部署&#xff1f;视硬件而定 在智能摄像头、工业质检终端和车载AI系统日益普及的今天&#xff0c;一个看似简单的问题却频繁困扰着嵌入式AI工程师&#xff1a;我们能不能直接把在服务器上跑得好好的 pytorch:2.6-cuda12.1 Docker镜像&a…

作者头像 李华
网站建设 2026/5/30 15:55:04

HID协议系统学习:主机与设备通信流程剖析

HID协议深度解析&#xff1a;从设备接入到数据交互的完整链路拆解你有没有想过&#xff0c;当你把一个USB键盘插进电脑时&#xff0c;系统是怎么立刻“认出”它是键盘而不是U盘&#xff1f;为什么不用装驱动就能打字&#xff1f;更神奇的是&#xff0c;同一个键盘在Windows、Ma…

作者头像 李华
网站建设 2026/6/15 11:40:21

深入理解image2lcd字节对齐与像素对应关系

深入理解 image2lcd 字节对齐与像素对应关系&#xff1a;从原理到实战 你有没有遇到过这样的情况&#xff1f;精心设计的图标导入 image2lcd &#xff0c;导出 C 数组烧进单片机后&#xff0c;LCD 屏幕上显示的图像却 上下颠倒、左右翻转、边缘错乱 &#xff0c;甚至出现诡…

作者头像 李华