likes
comments
collection

Nestjs使用sequelize完成多表操作(一对多、多对多)

作者站长头像
站长
· 阅读数 18

书接上回,上次的文章介绍了nestjs中sequelize操作单表(User表)。这次继续介绍多表操作。Role表与User表存在多对多关系(每个用户可以有多个角色,每个角色包含多个用户)。License(车牌)表与User表存在一对多关系(每辆车只能有一个户主,每个户主可以有多辆车)。

关于创建实例对象、关联数据表、nestjs引入sequelize等可以参考本专栏第一篇文章。本篇主要说明多表操作。 # Nestjs使用sequelize完成单表操作

前置说明。先看一下ER图直观的看一下四个表之间的关系

Nestjs使用sequelize完成多表操作(一对多、多对多)

先处理一对多关联.建立License表

// licenses/license.model.ts
import { Column, Table, Model, ForeignKey, BelongsTo } from 'sequelize-typescript';
import { User } from '../users/user.model';
@Table({
  tableName: 'user_license',
  timestamps: false,
})
export class License extends Model<License> {
  @Column
  license_num: string;
  
  @ForeignKey(() => User) // 定义user_id字段为外键,关联User表
  @Column
  user_id: number;
  
  @BelongsTo(() => User) // 定义多对一关系。注意使用BelongsTo是多对一关系的【多】表
  user: User; 
}

再处理多对多关联。多对多关系需要一张中间关联表。所以我们先建立一张RoleUser表。在表中声明外键。将User和Role关联。(注意在Role/User与RoleUser的关系是一对多。User与Role的关系才是多对多)

// role_users/role_user.model.ts
import { Column, Table, Model, BelongsTo, ForeignKey } from 'sequelize-typescript';
import { Role } from '../roles/role.model'; // 引入User表,
import { User } from '../users/user.model'; // 引入User表,注意:Role表等下再建立哈
@Table({
  tableName: 'admin_role_user', // 数据库中有改该表
  timestamps: false,
})
export class RoleUser extends Model<RoleUser> {

  @ForeignKey(() => User)
  @Column
  user_id: number; // 外键user_id关联到User表中的主键id
  @BelongsTo(() => User) // 同理定义多对一关系。注意使用BelongsTo是多对一关系的【多】表
  user: User[];

  @ForeignKey(() => Role)
  @Column
  role_id: number;// 外键role_id关联到User表中的主键id
  @BelongsTo(() => Role) 
  role: Role[];
}

再定义Role实例(Role表并不需要再和RoleUser关联。只需和User关联。同理User也只需要和Role关联)

// roles/role.model.ts
import { Column, Table, Model, BelongsToMany } from 'sequelize-typescript';
import { RoleUser } from '../role_users/role_user.model';
import { User } from '../users/user.model';

@Table({
  tableName: 'admin_role',
  timestamps: false,
})
export class Role extends Model<Role> {
  @Column
  name: string;
  @Column
  remarks: string;

  @BelongsToMany(() => User, () => RoleUser) // 建立多对多关联。第二个参数是中间表UserRole
  users: User[];
}

大家也能想到User表中的结构了

import { Column, Table, Model, HasMany, BelongsToMany } from 'sequelize-typescript';
import { License } from '../licenses/license.model';
import { RoleUser } from '../role_users/role_user.model';
import { Role } from '../roles/role.model';
@Table({
  tableName: 'admin_user',
  timestamps: false,
})
export class User extends Model<User> {
  @Column
  username: string;
  @Column
  password: string;
  @Column
  email: string;
  @Column
  mobile: string;
  @Column
  create_time: Date;

  @HasMany(() => License) // 一对多关系中的【一】表使用的hasmany。很语义化
  licenses: License[];

  @BelongsToMany(() => Role, () => RoleUser)
  roles: Role[];
}

下面再看一下users.service.ts中如何使用User实例

// users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { User } from './user.model';
import { License } from '../licenses/license.model';
import { Role } from '../roles/role.model';
import { RoleUser } from '../role_users/role_user.model';
@Injectable()
export class UsersService {
  constructor(
    @InjectModel(User)
    private userModel: typeof User
  ) {}

  findAll(): Promise<User[]> {
    return this.userModel.findAll({ 
      attributes: ['username'], // 指定查找User表中的部分字段
      include: [
        {
          model: Role, // 查表时包括Role表和License表。并且制定查出具体的字段。实例的具体方法可到官网学习
          attributes: ['remarks', 'name'],
        },
        {
          model: License,
          attributes: ['license_num'],
        },
      ],
    });
  }
}

Postman查表验证

Nestjs使用sequelize完成多表操作(一对多、多对多) 到此为止多表联查的操作就完成了。如果需要在多表中进行删除或者插入、更新操作还没有一次性完成的解决方案。希望大家不吝赐教。 NPM的sequelize-typescript英文文档