小满nestjs(第二十七章 nestjs typeOrm关系)

简介: 在我们开始的过程中,肯定不会把数据存在一个表里面,我们会进行分表,把数据分开存,然后通过关联关系,联合查询。

在我们开始的过程中,肯定不会把数据存在一个表里面,我们会进行分表,把数据分开存,然后通过关联关系,联合查询。


typeOrm 文档 一对一 | TypeORM 中文文档


前端代码还是复用上一章的 增加了一个添加Tag


<template>
    <div class="wraps">
        <div>
            <el-input v-model="search.keyWord" style="width:300px;"></el-input>
            <el-button @click="init" style="margin-left:10px;">搜索</el-button>
            <el-button @click="openDialog" type="primary" style="margin-left:10px;">添加</el-button>
        </div>
        <el-table border :data="tableData" style="width: 100%;margin-top: 30px;">
            <el-table-column prop="name" label="名字" />
            <el-table-column prop="desc" label="描述" />
            <el-table-column prop="id" label="id" />
            <el-table-column>
                <template #default="scope">
                    <el-button @click="edit(scope.row)">编辑</el-button>
                    <el-button @click="deleteRow(scope.row)">删除</el-button>
                    <el-button @click="(isShowTag = true,row = scope.row)">添加tag</el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination @current-change="change" style="float:right;margin-top:10px;" background
            layout="prev, pager, next" :total="total" />
    </div>
    <el-dialog v-model="dialogVisible" title="弹框" width="50%">
        <el-form :model="form">
            <el-form-item prop="name" label="名称">
                <el-input v-model="form.name" placeholder="名称" />
            </el-form-item>
            <el-form-item prop="desc" label="描述">
                <el-input v-model="form.desc" placeholder="描述">
                </el-input>
            </el-form-item>
        </el-form>
        <template #footer>
            <span class="dialog-footer">
                <el-button @click="close">关闭</el-button>
                <el-button type="primary" @click="save">
                    保存
                </el-button>
            </span>
        </template>
    </el-dialog>
    <el-dialog v-model="isShowTag" title="添加tag">
        <el-select style="width:100%" v-model="tags" multiple>
            <el-option value="tag1">tag1</el-option>
            <el-option value="tag2">tag2</el-option>
            <el-option value="tag3">tag3</el-option>
        </el-select>
        <template #footer>
            <el-button @click="addTa" type="primary">确定</el-button>
        </template>
    </el-dialog>
</template>
<script setup lang='ts'>
import { ref, reactive } from 'vue'
import type { FormInstance } from 'element-plus'
import { addUser, updateUser, delUser, getList, addTags } from '@/server'
const isShowTag = ref<boolean>(false)
const tags = ref<string[]>([])
const total = ref<number>(0)
const row = ref<{
    id?: number,
    name?: string,
    desc?: string,
    createTime?: Date
}>({})
const addTa = async () => {
    const res = await addTags({
        tags: tags.value,
        userId: row.value.id
    })
    isShowTag.value = false;
    tags.value = [];
}
//搜索框
const search = reactive({
    keyWord: "",
    page: 1,
    pageSize: 10
})
//表单
const form = reactive({
    name: "",
    desc: "",
    id: 0
})
//清空数据
const resetForm = reactive({ ...form })
//表格数据
const tableData = ref([])
//弹框开关
const dialogVisible = ref<boolean>(false)
const openDialog = () => {
    dialogVisible.value = true;
    Object.assign(form, resetForm)
}
//初始化表格数据
const init = async () => {
    const list = await getList(search)
    tableData.value = list?.data ?? [];
    total.value = list?.total ?? 0
}
init()
const change = (page) => {
    search.page = page;
    init()
}
//保存 和修改 表格数据
const save = async () => {
    if (form.id) {
        await updateUser(form)
    } else {
        await addUser(form)
    }
    close()
    init()
}
//删除表格数据
const deleteRow = async (row) => {
    await delUser({ id: row.id })
    init()
}
//获取 详情
const edit = (row: any) => {
    dialogVisible.value = true;
    Object.assign(form, row)
}
//关闭弹框
const close = () => {
    dialogVisible.value = false;
}
</script>
<style  lang='less'>
* {
    padding: 0;
    margin: 0;
}
html,
body {
    background: #ccc;
}
.wraps {
    height: 100vh;
    padding: 30px;
}
</style>


94d4f2437b004c54a9c9a9b114b6eb2c.png


新增了一个接口


import axios from 'axios'
axios.defaults.baseURL = 'http://localhost:3000'
export const addUser = (data) => axios.post('/user',data).then(res => res.data)
export const getList = (data) => axios.get('/user',{params:data}).then(res => res.data)
export const delUser = (data) => axios.delete(`/user/${data.id}`).then(res => res.data)
export const updateUser = (data) => axios.patch(`/user/${data.id}`,data).then(res => res.data)
//添加tag
export const addTags = (data) => axios.post(`/user/add/tags`,data).then(res => res.data)


后端Nestjs


1.新建一个 tags.entity.ts


定义Tags的数据表


import { Column, Entity, PrimaryGeneratedColumn, BeforeInsert, CreateDateColumn, Generated, OneToOne, JoinColumn, ManyToOne } from 'typeorm'
import { User } from './user.entity'
@Entity()
export class Tags {
    @PrimaryGeneratedColumn()
    id: number
    @Column()
    tags:string
    @ManyToOne(()=>User,(user)=>user.tags)
    @JoinColumn()
    user:User
} 


Modal 需要关联tag表


import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import {TypeOrmModule} from '@nestjs/typeorm'
import { User } from './entities/user.entity';
import { Tags } from './entities/tags.entity';
// import { example } from './entities/tags.entity';
@Module({
  imports:[TypeOrmModule.forFeature([User,Tags])],
  controllers: [UserController],
  providers: [UserService]
})
export class UserModule {}


然后user表跟tags表进行关联


import { Column, Entity, PrimaryGeneratedColumn, BeforeInsert, CreateDateColumn, Generated, OneToOne, JoinColumn, OneToMany } from 'typeorm'
import { Tags } from './tags.entity'
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number
  @Column({ type: "varchar", length: 255 })
  name: string
  @Column({ type: "text" })
  desc: string
  @Generated('uuid')
  uuid: string
  @CreateDateColumn({ type: "timestamp" })
  createTime: Date
  @OneToMany(() => Tags, (tags) => tags.user)
  tags:Tags[]
  // example: example
}


这儿我们解释一下  OneToMany 和 ManyToOne的用法


对于用户来说一个用户可以拥有多个tag 他们的关系是一对多 OneToMany

对于tag来说他们是多个tag指定单个用户 所以是  ManyToOne


8bc93fb3ba3a4344a1677787a67415af.png


OneToMany  接受两个参数


第一个参数是个函数返回关联的类 所以在user表关联tag

第二个参数 创建双向关系

ManyToOne 用法一样


@OneToMany(() => Tags, (tags) => tags.user)


保存该关系


沿用上一章的代码增加Controller 增加 addTags

import { Controller, Get, Post, Body, Patch, Param, Delete, Query } 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('/add/tags')
  addTags (@Body() params:{tags:string[],userId:number}) {
    return this.userService.addTags(params)
  }
  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }
  @Get()
  findAll(@Query() query:{keyWord:string,page:number,pageSize:number}) {
    return this.userService.findAll(query);
  }
  @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);
  }
}


service 增加 addTags 方法


import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { Repository, Like } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Tags } from './entities/tags.entity';
// import { example } from './entities/tags.entity';
@Injectable()
export class UserService {
  constructor(
  @InjectRepository(User) private readonly user: Repository<User>,
  @InjectRepository(Tags) private readonly tag: Repository<Tags>
  ) { }
//通过前端传入的userId 查到当前id 的用户信息,然后拿到前端传入的tags [tag1,tag2,tag3]
// 进行遍历 给tag实例进行赋值 然后调用保存方法添加tag 添加完之后 通过 tagList 保存该tag类
// 最后把tagList 赋给 user类的tags属性 然后重新调用save 进行更新
  async addTags (params:{tags:string[],userId:number}) {
    const userInfo = await this.user.findOne({where:{id:params.userId}})
    const tagList:Tags[] = []
    for (let i = 0;i<params.tags.length;i++) {
       let T =  new Tags()
       T.tags = params.tags[i];
       await this.tag.save(T)
       tagList.push(T)
    }
    userInfo.tags = tagList;
    console.log(userInfo,1)
    return this.user.save(userInfo)
  }
  async create(createUserDto: CreateUserDto) {
    const data = new User()
    // const ex = new example()
    data.name = createUserDto.name
    data.desc = createUserDto.desc
    // await this.example.save(ex)
    return this.user.save(data)
  }
  async findAll(query: { keyWord: string, page: number, pageSize: number }) {
    const data = await this.user.find({
      //查询的时候如果需要联合查询需要增加 relations
      relations:['tags'],
      where: {
        name: Like(`%${query.keyWord}%`)
      },
      order:{
        id:"DESC",
      },
      skip: (query.page - 1) * query.pageSize,
      take: query.pageSize
    })
    const total = await this.user.count({
      where: {
        name: Like(`%${query.keyWord}%`)
      },
    })
    return {
      data,
      total
    }
  }
  update(id: number, updateUserDto: UpdateUserDto) {
    return this.user.update(id, updateUserDto)
  }
  remove(id: number) {
    return this.user.delete(id)
  }
}


65692d88b0da4fefb7c44bd8e618d268.png

24eab02331b943a3a9beaa389694dc5a.png


如果需要联合查询需要增加   relations 注意看上面的代码

目录
相关文章
|
2月前
|
数据库
小满nestjs(第二十八章 nestjs 事务)
小满nestjs(第二十八章 nestjs 事务)
125 0
小满nestjs(第二十八章 nestjs 事务)
|
前端开发
小满nestjs(第十章 nestjs 提供者)
如果服务 之间有相互的依赖 或者逻辑处理 可以使用 useFactory
143 0
小满nestjs(第十章 nestjs 提供者)
|
9月前
|
开发框架 JavaScript 前端开发
nestjs的学习(一)
nestjs的学习(一)
50 0
|
中间件
小满nestjs(第十二章 nestjs 中间件)
中间件是在路由处理程序 之前 调用的函数。 中间件函数可以访问请求和响应对象
191 0
小满nestjs(第十二章 nestjs 中间件)
|
存储 JSON 关系型数据库
小满nestjs(第二十五章 nestjs 实体)
nullable: boolean - 在数据库中使列NULL或NOT NULL。 默认情况下,列是nullable:false。
234 0
小满nestjs(第二十五章 nestjs 实体)
|
JavaScript API
小满nestjs(第十五章 nestjs 和 RxJs)
nterval 五百毫秒执行一次 pipe 就是管道的意思 管道里面也是可以去掉接口的支持处理异步数据 去处理数据 这儿展示 了 map 和 filter 跟数组的方法是一样的 最后 通过观察者 subscribe 接受回调
87 0
小满nestjs(第十五章 nestjs 和 RxJs)
小满nestjs(第十一章 nestjs 模块)
每个 Nest 应用程序至少有一个模块,即根模块。根模块是 Nest 开始安排应用程序树的地方。事实上,根模块可能是应用程序中唯一的模块,特别是当应用程序很小时,但是对于大型程序来说这是没有意义的。在大多数情况下,您将拥有多个模块,每个模块都有一组紧密相关的功能
102 0
小满nestjs(第十一章 nestjs 模块)
|
前端开发
小满nestjs(第九章 nestjs Session)
session 是服务器 为每个用户的浏览器创建的一个会话对象 这个session 会记录到 浏览器的 cookie 用来区分用户
283 0
小满nestjs(第九章 nestjs Session)
|
前端开发 测试技术 API
小满nestjs(第八章 nestjs 控制器)
小满nestjs(第八章 nestjs 控制器)
167 0
小满nestjs(第八章 nestjs 控制器)
|
开发框架 JSON JavaScript
小满nestjs(第一章 介绍nestjs)
Nestjs 是一个用于构建高效可扩展的一个基于Node js 服务端 应用程序开发框架并且完全支持typeScript 结合了 AOP 面向切面的编程方式
191 0
小满nestjs(第一章 介绍nestjs)