问题描述
我正在使用 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 个字段。 请看那个表
现在如果我调用一个 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 的值。
任何人都可以有解决方案和指导方针,在这种情况下我应该怎么做?
解决方法
为什么有 eventEventId
和 userUserId
列
在 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
的实际数据库表中,应该有eventEventId
和userUserId
列创建为外键引用(这也是您目前看到的)。
为什么您的 user_id
与 userUserId
相似
现在,如果您查看 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
表应该只有 eventId
和 userId
列作为外键引用。
希望对你有帮助。干杯?!