实战使用 NestJS 搭建一个 Admin 后台服务 - 01. 项目搭建、配置文件和路由
实战使用 NestJS 搭建一个 Admin 后台服务 - 02. typeorm 操作 mysql&基础 crud
上一篇已经搭建好基本的框架,本篇将开始使用 typeorm 操作 mysql 数据库,实现 crud 操作,以及入参校验。直接开整。
GitHub 项目地址,欢迎各位大佬 Star。
mysql 数据库自备
一、引入 typeorm
1、依赖安装
bash
yarn add @nestjs/typeorm typeorm mysql2
2、配置文件修改
- 修改 config/config.ts
ts
export default () => ({
port: parseInt(process.env.PORT, 10) || 3003,
database: {
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10) || 3306,
username: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_DATABASE,
},
});
- 修改.env
bash
# 端口
PORT=3003
# 数据库配置
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USER=root
DATABASE_PASSWORD=q847164495
DATABASE_DATABASE=nest_demo # 数据库名自行设置
- 修改 app.module.ts 文件
ts
import { Module } from '@nestjs/common';
import { UsersModule } from './routers/users/users.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
import config from 'config/config';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
/** 环境变量配置 */
ConfigModule.forRoot({
isGlobal: true,
load: [config],
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule], // 记得导入 ConfigModule
/** 配置的使用 */
useFactory: async (configService: ConfigService) => ({
type: 'mysql',
host: configService.get<string>('database.host'),
port: configService.get<number>('database.port'),
username: configService.get<string>('database.username'),
password: configService.get<string>('database.password'),
database: configService.get<string>('database.database'),
synchronize: true,
autoLoadEntities: true,
timezone: '+08:00', // 东八时区
}),
inject: [ConfigService],
}),
UsersModule,
],
})
export class AppModule {}
二、开始基础的 crud 操作
1、修改实体类
- 修改 users/entities/users.entity.ts
- @Entity() 装饰类 标记为实体
ts
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity()
export class User {
/** 每个实体必须至少有一个主列 */
@PrimaryGeneratedColumn()
id: number;
/** @CreateDateColumn 是一个特殊列,自动为实体插入日期。无需设置此列,该值将自动设置。 */
@CreateDateColumn({
type: 'timestamp',
nullable: false,
name: 'create_time',
comment: '创建时间',
})
createTime: Date;
/** @UpdateDateColumn 是一个特殊列,在每次调用实体管理器或存储库的save时,自动更新实体日期。无需设置此列,该值将自动设置。 */
@UpdateDateColumn({
type: 'timestamp',
nullable: false,
name: 'update_time',
comment: '更新时间',
})
updateTime: Date;
@Column({ unique: true, nullable: true, comment: '用户名' })
username: string;
@Column({ unique: true, nullable: true, comment: '邮箱' })
email: string;
@Column({ unique: true, nullable: true, comment: '手机号' })
phone: string;
@Column({ nullable: true, comment: '头像' })
avatar: string;
@Column({ nullable: true, comment: '密码' })
password: string;
}
2、创建数据库
- 数据库名和配置一致
- npm run start 启动项目 orm 会自动进行数据库迁移(可自行关闭)
- 主要就是依赖 @Entity() 装饰的类
可以看到数据库里已经创建好了表
三、操作数据库进行 crud
1、module 导入
- 修改 users/dto/create-user.dto.ts
- users/dto/update-user.dto.ts 看情况修改,一般不需要修改
- 下篇中参数检验需要用到
ts
import { User } from '../entities/user.entity';
export class CreateUserDto extends User {}
ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto';
/** 直接继承了 且 声明为可选参数 */
export class UpdateUserDto extends PartialType(CreateUserDto) {}
- src/types/global.d.ts 创建该文件,写全局类型
ts
declare namespace Global {
type RuleResType<T> = {
code: number;
message: string;
data: T;
total?: number;
};
}
- 修改 users.module.ts 文件
ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
@Module({
/** 导入数据库实体类 */
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
- 编写 service,修改 users.service.ts 文件
ts
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { DeleteResult, Repository, UpdateResult } from 'typeorm';
import { User } from './entities/user.entity';
@Injectable()
export class UsersService {
/** s实体注册 */
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
async create(
createUserDto: CreateUserDto,
): Promise<Global.RuleResType<User>> {
const { username, password, email, phone, avatar } = createUserDto;
const data = await this.userRepository.save({
username,
password,
email,
phone,
avatar,
});
return { code: 200, message: '创建成功', data };
}
async findAll(): Promise<Global.RuleResType<User[]>> {
const data = await this.userRepository.find();
return { code: 200, message: '查询成功', data };
}
async findOne(id: number): Promise<Global.RuleResType<User>> {
const data = await this.userRepository.findOne({ where: { id: id } });
return { code: 200, message: '查询成功', data };
}
async update(
id: number,
updateUserDto: UpdateUserDto,
): Promise<Global.RuleResType<UpdateResult>> {
const data = await this.userRepository.update(id, updateUserDto);
return { code: 200, message: '更新成功', data };
}
async remove(id: number): Promise<Promise<Global.RuleResType<DeleteResult>>> {
const data = await this.userRepository.delete(id);
return { code: 200, message: '删除成功', data };
}
}
- users.controller 暂不修改
四、接口测试
-
npm run start
-
创建接口 注意@Column({ unique: true, nullable: true, comment: '用户名' }) 时unique 的唯一性
- 查询接口
- 更新
- 删除
下一篇
本篇已经完成了基本的curd,下篇将介绍参数校验,以及使用 swagger 生成接口文档,同时直接导入apifox使用