nest守卫 装饰器 swagger typeorm数据库连接
nest g gu 创建守卫
controller中引入
@UseGuards(UserGuard) // 可以放在方法上也可以放在类上
@SetMetadata('role','admin')//放在类上 检验是否拥有role权限admin
guard中注入 反射
constructor(private Relector:Reflector){}
//此方式拿到类源信息
const admin = this.Relector.get('role',context.getHandler())
自定义装饰器类似于java 的自定义注解
nest g d
其实就是封装了一下SetMetadata
import { SetMetadata } from '@nestjs/common';
export const Role = (...args: string[]) => SetMetadata('role', args);
自定义参数装饰器
export const ReqUrl = createParamDecorator((data:string,ctx:ExecutionContext) =>{
return ctx.switchToHttp().getRequest<Request>().originalUrl
})
//使用
findAll(@ReqUrl() url:string)
swagger接口文档
依赖
npm install @nestjs/swagger swagger-ui-exp
main.ts 中引入
const options = new DocumentBuilder().setTitle('小海海').setDescription('一段迷人的描述').setVersion('1').build()
const document = SwaggerModule.createDocument(app,options)
SwaggerModule.setup('/api-docs',app,document)
@ApiTags() // 分组的 放在 controller类上
@ApiOperation({summary:'描述',description:'额描述'}) // 接口描述的
@ApiParam()
@Apiquery
@Apiresponse() //添加在controller方法中的 描述了该方法的返回了些什么东西
@Apipropertiy()// DTO上面描述字段的
@ApiBearerAuth() // 这个很重要 JTW验证 可以自动给你添加token 需要在main中配置
typeorm
npm install -- save @nestjs/typeorm typeorm mysql2
module 中 imports 引入
TypeOrmModule.forRoot({
type:'mysql',
username:'root',
password:'1234',
host:'192.168.2.2',
database:'test',
port:3306,
autoLoadEntities:true,
synchronize:true
})
建立entry 这个是与数据库对应的 用来建表的
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Shop {
@PrimaryGeneratedColumn()
id:string
@Column()
name:string
@Column()
price:number
@Column()
describe:string
}
建立DTO (data translation object) 这个是与数据传输有关的
import { IsNumber, IsString } from "class-validator"
export class CreateShopDto {
@IsString()
name:string
@IsNumber()
price:number
@IsString()
describe:string
}
接下来在模块中引入
imports:[TypeOrmModule.forFeature([Shop])],
service 中使用工厂方法
import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateShopDto } from './dto/create-shop.dto';
import { UpdateShopDto } from './dto/update-shop.dto';
import { InjectRepository} from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Shop } from './entities/shop.entity';
@Injectable()
export class ShopService {
constructor(@InjectRepository(Shop) private readonly repository:Repository<Shop>){}
create(createShopDto: CreateShopDto) {
const shop =this.repository.create(createShopDto)
return this.repository.save(shop)
}
findAll() {
return this.repository.find()
}
async findOne(id: string) {
const shop = await this.repository.findOneBy({id:id})
if(shop == undefined){
throw new NotFoundException('meizhaodao ')
}
return shop
}
async update(id: string, updateShopDto: UpdateShopDto) {
console.log(id);
const shop = await this.repository.findOneBy({id})
if(updateShopDto.describe != null){
shop.describe = updateShopDto.describe
}
if(updateShopDto.name != null){
shop.name = updateShopDto.name
}
if(updateShopDto.price != null){
shop.price = updateShopDto.price
}
if(shop === undefined){
throw new NotFoundException('meizhaodao ')
}
return this.repository.save(shop)
}
async remove(id: string) {
const shop = await this.repository.preload({
id
})
if(shop == undefined){
throw new NotFoundException('meizhaodao ')
}
return this.repository.remove(shop)
}
}
数据库关系 一对一(OneToOne) 一对多(OneToMany)多对多(ManytoMany)
以此为例子 shop中添加一个features的数组
import { type } from "os";
import { Column, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn } from "typeorm";
import { Feature } from "./feature.entity";
@Entity()
export class Shop {
@PrimaryGeneratedColumn()
id:string
@Column()
name:string
@Column()
price:number
@Column()
describe:string
@JoinTable()
@ManyToMany(type => Feature,(feature) => feature.shops)
features:string[]
}
添加一个特性 通过 @ManyToMany(type => Feature,(feature) => feature.shops) 相关联 他会自动创建表格
nest g class /path/feature.eneity
import { type } from "os";
import { Column, Entity, ManyToMany, PrimaryColumn } from "typeorm";
import { Shop } from "./shop.entity";
@Entity()
export class Feature {
@PrimaryGeneratedColumn()
id:number
@Column()
name:string
@ManyToMany(type => Shop, shop=>shop.features)
shops:Shop[]
}
不要忘记在模块中注入 Feature
imports:[TypeOrmModule.forFeature([Shop,Feature])],
于是乎你的查询就需要改变了
通过给定的options
findAll() {
return this.repository.find({
relations:['features']
})
}
creat update
给shop 实体的feature注解添加参数 cascade:true 并将类型改为 Feature
@JoinTable()
@ManyToMany(type => Feature,(feature) => feature.shops,{
cascade:true
})
features:Feature[]
在service中注入 Feature的工厂方法并添加 相关的查找方法
@InjectRepository(Feature) private readonly featureRespository:Repository<Feature>
async perloadFetaure(name: string): Promise<Feature> {
const featuer = await this.featureRespository.findOneBy({ name: name })
// 如果有就直接返回
if (featuer) {
return featuer
}
//没有的话则添加一个由于开启了cascade:true 所以不需要save 他会自动添加
return this.featureRespository.create({ name: name })
}
改造create方法
async create(createShopDto: CreateShopDto) {
const features = await Promise.all(
createShopDto.features.map(name => this.perloadFetaure(name))
)
const shop = this.repository.create({
...createShopDto,
features
})
return this.repository.save(shop)
}
改造updata 方法
async update(id: string, updateShopDto: UpdateShopDto) {
console.log(id);
const features = updateShopDto.features && (await Promise.all(
updateShopDto.features.map(name => this.perloadFetaure(name))
))
const shop = await this.repository.preload({
id: +id,
...updateShopDto,
features
})
if (shop === undefined) {
throw new NotFoundException('meizhaodao ')
}
return this.repository.save(shop)
}
分页
首先添加一个公共的类
nest g class common/dto/pagination-query.dto --no-spec
import { Type } from "class-transformer"
import { IsOptional, IsPositive } from "class-validator"
export class PaginationQueryDto {
@IsOptional()//可选的 没有的话不至于报错
@IsPositive()// 确保是个正数
@Type(() =>Number) //由于传输的都是字符串 所以开启这个装饰器 使其变为数字 这个可以去掉如果说 在main中配置了全局的类型隐式转换
limit:number
@IsOptional()
@IsPositive()
@Type(() =>Number)
offset:number
}
/全局类型隐式转换/
app.useGlobalPipes(new ValidationPipe({
//whitelist:true,
transform:true,
transformOptions:{
enableImplicitConversion:true
}
}))
改造 findAll方法
service中 skip 与 take 来实现分页
@Get()
findAll(@Query()paginationQueryDto:PaginationQueryDto) {
return this.shopService.findAll(paginationQueryDto);
}
/*service*/
findAll(paginationQueryDto:PaginationQueryDto) {
const { limit ,offset} = paginationQueryDto
return this.repository.find({
relations: ['features'],
skip:offset,
take:limit
})
}