为什么 Typeorm 不填充连接列的数据?

问题描述

我正在使用 Typeorm、Typscript 和 Node 来构建一个应用程序来安排和管理直播活动。

在任何人开始提问之前,请仔细阅读问题信息。有点长,但我已经尽力描述每一个细节。

模型/event.ts

@Entity('user_events')
export class UserEvent extends NewBaseModel {
  @PrimaryGeneratedColumn({ name: 'event_id' })
  @IsNotEmpty()
  public eventId: number;

  @Column({ name: 'title',nullable: false })
  public title: string;

  @ManyToOne(type => User,user => user.events,{ onDelete: 'CASCADE' })
  @JoinColumn({ name: 'user_id' })
  public addedBy: User;

  @OnetoMany(() => EventMembers,member => member.event)
  public eventMembers: EventMembers[];

  @BeforeUpdate()
  public async updateDetails(): Promise<void> {
    this.updatedDate = moment().utc();
  }
}

模型/用户.ts

@Entity('users')
export class User extends NewBaseModel {
  @PrimaryGeneratedColumn({ name: 'user_id' })
  @IsNotEmpty()
  public userId: number;

  @IsNotEmpty()
  @Exclude()
  @Column({ name: 'password' })
  public password: string;

  @IsEmail()
  @Column({ name: 'email' })
  public email: string;

  @OnetoMany(type => UserEvent,event => event.addedBy)
  public events: UserEvent[];

  @OnetoMany(() => EventMembers,members => members.userId)
  public eventMembers: EventMembers[];
}

models/event-members.ts

@Entity('event_members')
export class EventMembers extends NewBaseModel {
  @PrimaryGeneratedColumn({ name: 'event_member_id' })
  @IsNotEmpty()
  public eventMemberId: number;

  @ManyToOne(type => UserEvent,event => event.eventMembers,{ onDelete: 'CASCADE' })
  @JoinColumn()
  public event: UserEvent;

  @ManyToOne(type => User,user => user.eventMembers,{ onDelete: 'CASCADE' })
  @JoinColumn()
  public user: User;

  @Column({ name: 'event_id' })
  public eventId: number;

  @Column({ name: 'user_id' })
  public userId: number;
  
  @BeforeInsert()
  public async hashPassword(): Promise<void> {
    this.createdDate = moment().format('YYYY-MM-DD HH:mm:ss');
  }

  @BeforeUpdate()
  public async updateDetails(): Promise<void> {
    this.updatedDate = moment().format('YYYY-MM-DD HH:mm:ss');
  }
}

event.controller.js

const event: UserEvent = await this.eventService.findOne({
    where: {
        eventId: eventParam.id,},relations: ['posters','eventMembers'],});

event.service.ts

public findOne(findCondition: any): Promise<any> {
  return this.eventRepository.findOne(findCondition);
}

以上是其他开发者已经写好的代码。现在我的问题是,当我评论模型/事件成员.ts 文件的以下代码时。现在执行删除和运行迁移的命令。

@Column({ name: 'event_id' })
public eventId: number;

@Column({ name: 'user_id' })
public userId: number;

查询未在响应中返回 user_id 和 event_id。以下是不包含 user_id 和 event_id 的响应。

UserEvent {
  uuid: 'd4ed7c0c-24f2-4cb3-8069-a8c3219bf157',eventId: 8,title: 'Christina Aguilera - Virtual Experiences',eventMembers: [
    EventMembers {
      createdDate: 2021-04-17T13:47:17.000Z,updatedDate: 2021-04-17T13:47:17.699Z,isDeleted: false,isActive: true,uuid: '41adc4b3-2e37-4c99-95d4-cfe4fb6b2005',eventMemberId: 64
    },EventMembers {
      createdDate: 2021-04-17T13:47:17.000Z,uuid: '3cde77f7-b332-4be2-94fa-a580ec729f57',eventMemberId: 65
    },uuid: 'ab91625d-89b4-43ef-b16f-87c2f1f50b36',eventMemberId: 66
    }
  ]
}

现在,如果我从模型文件中取消注释以下代码。现在我运行命令来删除并再次运行他的迁移。

@Column({ name: 'event_id' })
public eventId: number;

@Column({ name: 'user_id' })
public userId: number;

一旦我执行了上述步骤,并查看表格,它将添加另外 2 个字段。 请看那个表

。我在数据库添加了 2 个字段并描述了表

enter image description here

现在如果我调用一个 api 并执行上面描述的 event.controller.ts 代码,它会在 api 对象中响应我的 event_id 和 user_id。

UserEvent {
  uuid: 'a520ab78-1269-418d-9ecc-988bfe7dad95',eventId: 1,eventMembers: [
    EventMembers {
      createdDate: 2021-04-17T16:54:09.000Z,updatedDate: 2021-04-17T16:08:56.000Z,uuid: '30e835a0-babc-452b-9626-5178c05fa680',eventMemberId: 4,userId: 3
    },EventMembers {
      createdDate: 2021-04-17T16:54:09.000Z,uuid: 'a8e2418f-94be-4c5c-af38-c284685cd051',eventMemberId: 5,userId: 4
    },uuid: '8edb8b39-5095-4595-8460-1a402cec7fdb',eventMemberId: 6,userId: 6
    },]
}

如果您查看对象,该值现在包含 event_id 和 user_id 显示

现在我的问题是为什么会发生这种情况,为什么我无法从连接表中获取 event_id 和 user_id 的值。要直接访问表中的 event_id 和 user_id 值,我应该在数据库添加 2 个 redudent 列,并且两者都包含相同的值。

因为 event_id 列值类似于 eventEventId 列,而 user_id 列值类似于 userUserId 列。

我想从表中删除 event_id 和 user_id 列,无论如何,我可以使用 typeorm find() 函数查询响应中直接获取 event_id 和 user_id 的值。

任何人都可以有解决方案和指导方针,在这种情况下我应该怎么做?

解决方法

为什么有 eventEventIduserUserId

在 typeorm 中,当您有 @ManyToOne 关系时,如果您没有在 @JoinColumn 中指定自定义参数,这将在数据库表中创建一个新列来保持关系。默认情况下为 propertyName + referencedColumnName。查看documentation了解更多信息。

您的 EventMembers 实体具有 @ManyToOne 关系,如下所示:

@Entity('event_members')
export class EventMembers extends NewBaseModel {
  ...

  @ManyToOne(type => UserEvent,event => event.eventMembers,{ onDelete: 'CASCADE' })
  @JoinColumn()
  public event: UserEvent;

  @ManyToOne(type => User,user => user.eventMembers,{ onDelete: 'CASCADE' })
  @JoinColumn()
  public user: User;
  
  ...
}

这意味着在event_members的实际数据库表中,应该有eventEventIduserUserId列创建为外键引用(这也是您目前看到的)。


为什么您的 user_iduserUserId 相似

现在,如果您查看 User 实体,您已经定义了相关的 @OneToMany 关系,如下所示:

@Entity('users')
export class User extends NewBaseModel {
  ...

  @OneToMany(() => EventMembers,members => members.userId)
  public eventMembers: EventMembers[];
}

我相信代码的 members => members.userId 部分是您将看到 userUserId 的值与 user_id 相似的原因。理想情况下,应该将其定义为 members => members.user 以避免这种混淆。

当你说,

现在,如果我从模型文件中取消注释以下代码。现在我运行命令来删除并再次运行他的迁移。

我相信您必须对上述关系进行一些更改,否则当您注释掉 userId 实体的​​ EventMembers 属性时,User 实体中的上述关系应该有语法错误.

但是,我不知道您的 event_id 列值与 eventEventId 列值有何相似之处。


解决方案

将您的 User 实体更改如下:

@Entity('users')
export class User extends NewBaseModel {
  ...

  @OneToMany(() => EventMembers,members => members.user)
  public eventMembers: EventMembers[];
}

将您的 EventMembers 实体更改如下:

@Entity('event_members')
export class EventMembers extends NewBaseModel {
  ...

  @ManyToOne(type => UserEvent,{ onDelete: 'CASCADE' })
  @JoinColumn({ name: 'eventId' })
  public event: UserEvent;

  @ManyToOne(type => User,{ onDelete: 'CASCADE' })
  @JoinColumn({ name: 'userId' })
  public user: User;

  @Column({ name: 'eventId' })
  public eventId: number;

  @Column({ name: 'userId' })
  public userId: number;
  ...
}

现在您的 event_members 表应该只有 eventIduserId 列作为外键引用。

希望对你有帮助。干杯?!