TypeORM 无关联关系的mysql多表连接查询

  TypeORM 官方给的文档中,多表查询时使用的是通过实体关系进行leftjoin查询,我们知道TypeORM实体关系实际上是通过mysql的外键实现的。在实际开发中,外键因为有诸多限制不被推荐使用,大部分的都是无关系的表连接。经过几天的查找资料和摸索,找到了两种查询的方法,总结一下,如果大家有其他好的方法,欢迎留言讨论。

定义实体类

User 实体
import { Entity, Column, PrimaryColumn } from 'typeorm';
@Entity()
export class User {
  @PrimaryColumn()
  id: string;

  @Column()
  nickname: string;

  @Column()
  gender: number;

  @Column()
  avatarUrl: string;

  @Column()
  language: string;

  @Column()
  country: string;

  @Column()
  province: string;

  @Column()
  city: string;
}
Role 实体类
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Role {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  roleId: number;

  @Column()
  userId: string;
}
Role_dic 实体类
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Role_dic {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  roleId: number;

  @Column()
  roleName: string;
}
表关系
user.id = role.userId  role.roleId = role_dic.roleId

User service查询的两种方式

方法一
    // 查询语句
    let queryBuilder = this.connection.createQueryBuilder(User, 'user');
    const user = await queryBuilder
    .leftJoinAndSelect(Role, 'role', 'role.userId = user.id')
    .leftJoinAndSelect(Role_dic, 'role_dic', 'role_dic.roleId = role.roleId')
    .where("user.id = :id", { id: userId })
    .select(`
      user.id as id,
      user.nickname as nickname,
      user.gender as gender,
      user.avatarUrl as avatarUrl,
      user.language as language,
      user.country as country,
      user.province as province,
      user.city as city,
      role.roleId as roleId,
      role_dic.roleName as roleName
    `)
    .getRawOne();

// 返回结果
{
    "id": "1630404672291",
    "nickname": "xiaoditian",
    "gender": 1,
    "avatarUrl": "mytouxiang",
    "language": "cn",
    "country": "china",
    "province": "henan",
    "city": "zhengzhou",
    "roleId": 1,
    "roleName": "管理员"
}

  这种方法使用getRawOne获取到sql查询后的原始数据,因为TypeORM会用别名,所以这里用select对字段进行了重命名,这个写法需要对每个需要的字段名进行重命名,否则返回的字段名称会带上表名。

方法二
//查询语句
let queryBuilder = this.connection.createQueryBuilder(User, 'user');
const user = await queryBuilder
      .leftJoinAndMapOne('user.role', Role, 'role', 'role.userId = user.id')
      .leftJoinAndMapOne('role.roleDic', Role_dic, 'role_dic', 'role_dic.roleId = role.roleId')
      .where("user.id = :id", { id: userId })
      .getOne();
//返回结果

{
    "id": "1630404672291",
    "nickname": "xiaoditian",
    "gender": 1,
    "avatarUrl": "mytouxiang",
    "language": "cn",
    "country": "china",
    "province": "henan",
    "city": "zhengzhou",
    "role": {
        "id": 1,
        "roleId": 1,
        "userId": "1630404672291",
        "roleDic": {
            "id": 1,
            "roleId": 1,
            "roleName": "管理员"
        }
    }
}

  第二种方法使用leftJoinAndMapOne作字段映射,如果一对多可以使用leftJoinAndMapMany。这样就不用挨个对字段重命名,但是可能存在嵌套较深的问题。

总结

  以上是常用的两种表连接的方法,每个都有其优缺点,可以根据情况选择使用。两外附上这两种方法的出处:
1、https://juejin.cn/post/6916483483095449608
2、https://www.cnblogs.com/zzk96/p/11397223.html

你可能感兴趣的:(TypeORM 无关联关系的mysql多表连接查询)