飞道的博客

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

306人阅读  评论(0)

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

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

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


  
  1. <template>
  2. <div class="wraps">
  3. <div>
  4. <el-input v-model="search.keyWord" style="width:300px;"> </el-input>
  5. <el-button @click="init" style="margin-left:10px;">搜索 </el-button>
  6. <el-button @click="openDialog" type="primary" style="margin-left:10px;">添加 </el-button>
  7. </div>
  8. <el-table border :data="tableData" style="width: 100%;margin-top: 30px;">
  9. <el-table-column prop="name" label="名字" />
  10. <el-table-column prop="desc" label="描述" />
  11. <el-table-column prop="id" label="id" />
  12. <el-table-column>
  13. <template #default="scope">
  14. <el-button @click="edit(scope.row)">编辑 </el-button>
  15. <el-button @click="deleteRow(scope.row)">删除 </el-button>
  16. <el-button @click="(isShowTag = true,row = scope.row)">添加tag </el-button>
  17. </template>
  18. </el-table-column>
  19. </el-table>
  20. <el-pagination @current-change="change" style="float:right;margin-top:10px;" background
  21. layout= "prev, pager, next" :total= "total" />
  22. </div>
  23. <el-dialog v-model="dialogVisible" title="弹框" width="50%">
  24. <el-form :model="form">
  25. <el-form-item prop="name" label="名称">
  26. <el-input v-model="form.name" placeholder="名称" />
  27. </el-form-item>
  28. <el-form-item prop="desc" label="描述">
  29. <el-input v-model="form.desc" placeholder="描述">
  30. </el-input>
  31. </el-form-item>
  32. </el-form>
  33. <template #footer>
  34. <span class="dialog-footer">
  35. <el-button @click="close">关闭 </el-button>
  36. <el-button type="primary" @click="save">
  37. 保存
  38. </el-button>
  39. </span>
  40. </template>
  41. </el-dialog>
  42. <el-dialog v-model="isShowTag" title="添加tag">
  43. <el-select style="width:100%" v-model="tags" multiple>
  44. <el-option value="tag1">tag1 </el-option>
  45. <el-option value="tag2">tag2 </el-option>
  46. <el-option value="tag3">tag3 </el-option>
  47. </el-select>
  48. <template #footer>
  49. <el-button @click="addTa" type="primary">确定 </el-button>
  50. </template>
  51. </el-dialog>
  52. </template>
  53. <script setup lang='ts'>
  54. import { ref, reactive } from 'vue'
  55. import type { FormInstance } from 'element-plus'
  56. import { addUser, updateUser, delUser, getList, addTags } from '@/server'
  57. const isShowTag = ref<boolean>( false)
  58. const tags = ref<string[]>([])
  59. const total = ref<number>( 0)
  60. const row = ref<{
  61. id?: number,
  62. name?: string,
  63. desc?: string,
  64. createTime?: Date
  65. }>({})
  66. const addTa = async ( ) => {
  67. const res = await addTags({
  68. tags: tags. value,
  69. userId: row. value. id
  70. })
  71. isShowTag. value = false;
  72. tags. value = [];
  73. }
  74. //搜索框
  75. const search = reactive({
  76. keyWord: "",
  77. page: 1,
  78. pageSize: 10
  79. })
  80. //表单
  81. const form = reactive({
  82. name: "",
  83. desc: "",
  84. id: 0
  85. })
  86. //清空数据
  87. const resetForm = reactive({ ...form })
  88. //表格数据
  89. const tableData = ref([])
  90. //弹框开关
  91. const dialogVisible = ref<boolean>( false)
  92. const openDialog = ( ) => {
  93. dialogVisible. value = true;
  94. Object. assign(form, resetForm)
  95. }
  96. //初始化表格数据
  97. const init = async ( ) => {
  98. const list = await getList(search)
  99. tableData. value = list?. data ?? [];
  100. total. value = list?. total ?? 0
  101. }
  102. init()
  103. const change = ( page) => {
  104. search. page = page;
  105. init()
  106. }
  107. //保存 和修改 表格数据
  108. const save = async ( ) => {
  109. if (form. id) {
  110. await updateUser(form)
  111. } else {
  112. await addUser(form)
  113. }
  114. close()
  115. init()
  116. }
  117. //删除表格数据
  118. const deleteRow = async ( row) => {
  119. await delUser({ id: row. id })
  120. init()
  121. }
  122. //获取 详情
  123. const edit = ( row: any) => {
  124. dialogVisible. value = true;
  125. Object. assign(form, row)
  126. }
  127. //关闭弹框
  128. const close = ( ) => {
  129. dialogVisible. value = false;
  130. }
  131. </script>
  132. <style lang='less'>
  133. * {
  134. padding: 0;
  135. margin: 0;
  136. }
  137. html,
  138. body {
  139. background: #ccc;
  140. }
  141. .wraps {
  142. height: 100vh;
  143. padding: 30px;
  144. }
  145. </style>

 新增了一个接口


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

后端Nestjs

1.新建一个 tags.entity.ts

定义Tags的数据表


  
  1. import { Column, Entity, PrimaryGeneratedColumn, BeforeInsert, CreateDateColumn, Generated, OneToOne, JoinColumn, ManyToOne } from 'typeorm'
  2. import { User } from './user.entity'
  3. @Entity()
  4. export class Tags {
  5. @PrimaryGeneratedColumn()
  6. id: number
  7. @Column()
  8. tags:string
  9. @ManyToOne(()=>User,(user)=>user.tags)
  10. @JoinColumn()
  11. user:User
  12. }

Modal 需要关联tag表


  
  1. import { Module } from '@nestjs/common';
  2. import { UserService } from './user.service';
  3. import { UserController } from './user.controller';
  4. import {TypeOrmModule} from '@nestjs/typeorm'
  5. import { User } from './entities/user.entity';
  6. import { Tags } from './entities/tags.entity';
  7. // import { example } from './entities/tags.entity';
  8. @Module({
  9. imports:[TypeOrmModule.forFeature([User,Tags])],
  10. controllers: [UserController],
  11. providers: [UserService]
  12. })
  13. export class UserModule {}

然后user表跟tags表进行关联


  
  1. import { Column, Entity, PrimaryGeneratedColumn, BeforeInsert, CreateDateColumn, Generated, OneToOne, JoinColumn, OneToMany } from 'typeorm'
  2. import { Tags } from './tags.entity'
  3. @Entity()
  4. export class User {
  5. @PrimaryGeneratedColumn()
  6. id: number
  7. @Column({ type: "varchar", length: 255 })
  8. name: string
  9. @Column({ type: "text" })
  10. desc: string
  11. @Generated('uuid')
  12. uuid: string
  13. @CreateDateColumn({ type: "timestamp" })
  14. createTime: Date
  15. @OneToMany(() => Tags, (tags) => tags.user)
  16. tags:Tags[]
  17. // example: example
  18. }

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

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

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

 OneToMany  接受两个参数

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

第二个参数 创建双向关系

ManyToOne 用法一样

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

保存该关系

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


  
  1. import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common';
  2. import { UserService } from './user.service';
  3. import { CreateUserDto } from './dto/create-user.dto';
  4. import { UpdateUserDto } from './dto/update-user.dto';
  5. @Controller('user')
  6. export class UserController {
  7. constructor(private readonly userService: UserService) {}
  8. @Post('/add/tags')
  9. addTags (@Body() params:{tags:string[],userId:number}) {
  10. return this.userService.addTags(params)
  11. }
  12. @Post()
  13. create(@Body() createUserDto: CreateUserDto) {
  14. return this.userService.create(createUserDto);
  15. }
  16. @Get()
  17. findAll(@Query() query:{keyWord:string,page:number,pageSize:number}) {
  18. return this.userService.findAll(query);
  19. }
  20. @Patch(':id')
  21. update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
  22. return this.userService.update(+id, updateUserDto);
  23. }
  24. @Delete(':id')
  25. remove(@Param('id') id: string) {
  26. return this.userService.remove(+id);
  27. }
  28. }

service 增加 addTags 方法


  
  1. import { Injectable } from '@nestjs/common';
  2. import { CreateUserDto } from './dto/create-user.dto';
  3. import { UpdateUserDto } from './dto/update-user.dto';
  4. import { Repository, Like } from 'typeorm';
  5. import { InjectRepository } from '@nestjs/typeorm';
  6. import { User } from './entities/user.entity';
  7. import { Tags } from './entities/tags.entity';
  8. // import { example } from './entities/tags.entity';
  9. @Injectable()
  10. export class UserService {
  11. constructor(
  12. @InjectRepository(User) private readonly user: Repository <User>,
  13. @InjectRepository(Tags) private readonly tag: Repository <Tags>
  14. ) { }
  15. //通过前端传入的userId 查到当前id 的用户信息,然后拿到前端传入的tags [tag1,tag2,tag3]
  16. // 进行遍历 给tag实例进行赋值 然后调用保存方法添加tag 添加完之后 通过 tagList 保存该tag类
  17. // 最后把tagList 赋给 user类的tags属性 然后重新调用save 进行更新
  18. async addTags (params:{tags:string[],userId:number}) {
  19. const userInfo = await this.user.findOne({where:{id:params.userId}})
  20. const tagList:Tags[] = []
  21. for (let i = 0;i<params.tags.length;i++) {
  22. let T = new Tags()
  23. T.tags = params.tags[i];
  24. await this.tag.save(T)
  25. tagList.push(T)
  26. }
  27. userInfo.tags = tagList;
  28. console.log(userInfo,1)
  29. return this.user.save(userInfo)
  30. }
  31. async create(createUserDto: CreateUserDto) {
  32. const data = new User()
  33. // const ex = new example()
  34. data.name = createUserDto.name
  35. data.desc = createUserDto.desc
  36. // await this.example.save(ex)
  37. return this.user.save(data)
  38. }
  39. async findAll(query: { keyWord: string, page: number, pageSize: number }) {
  40. const data = await this.user.find({
  41. //查询的时候如果需要联合查询需要增加 relations
  42. relations:['tags'],
  43. where: {
  44. name: Like(`%${query.keyWord}%`)
  45. },
  46. order:{
  47. id:"DESC",
  48. },
  49. skip: (query.page - 1) * query.pageSize,
  50. take: query.pageSize
  51. })
  52. const total = await this.user.count({
  53. where: {
  54. name: Like(`%${query.keyWord}%`)
  55. },
  56. })
  57. return {
  58. data,
  59. total
  60. }
  61. }
  62. update(id: number, updateUserDto: UpdateUserDto) {
  63. return this.user.update(id, updateUserDto)
  64. }
  65. remove(id: number) {
  66. return this.user.delete(id)
  67. }
  68. }

 

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


转载:https://blog.csdn.net/qq1195566313/article/details/128379605
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场