TypeORM 更新 Mant-to-Many 关系的所有记录

Dav*_*ell 2 typescript typeorm

Channel我在和之间有多对多关系User,用于向订阅频道的用户发送电子邮件通知。我正在开发一项功能,其中一个通道被溶解以支持另一个通道,但我不知道如何将所有通知从溶解通道传输到目标通道。


@Entity()
export class User {
    @PrimaryColumn()
    id: string

    @Column()
    createdAt: Date

    @Column()
    updatedAt: Date

    @Column()
    email: string

    @ManyToMany(_type => Channel)
    @JoinTable()
    notifications: Channel[]
}

@Entity()
export class Channel {
    @PrimaryColumn()
    id: string

    @Column()
    createdAt: Date

    @Column()
    updatedAt: Date
}

async function transferNotifications(from: unknown, to: unknown): Promise<void> {
    //?
}
Run Code Online (Sandbox Code Playgroud)

iY1*_*1NQ 8

您至少有两个选择:

\n\n

1. 使用EntityManager

\n\n

首先,获取User与 已解析关系的所有实体notificationChannel然后从notification所有获取的实体的属性中删除旧的(已溶解的)实体User,并将新Channel实体添加到该数组(如果它以前包含旧实体)。这将删除相应的连接表行并向新通道添加一个新行。

\n\n

明显的缺点是,将在三个表的所有行上执行联接,所有结果都会加载到应用程序内存中。因此对于较大的表来说不一定是一个好的解决方案。

\n\n

2. 使用 QueryBuilder

\n\n

更好的方法是通过添加自定义联接表实体来自行构建联接表。然后使用QueryBuilder新通道的 id 替换旧通道的旧外键。

\n\n
getRepository(UserChannel).createQueryBuilder()\n   .update()\n   .set({ channelId: \'<new channel id>\' })\n   .where(`channelId = :channelId`, { channelId: `<old channel id>`})\n   .execute();\n
Run Code Online (Sandbox Code Playgroud)\n\n
@Entity()\nexport class User {\n\n    @PrimaryColumn()\n    id: string\n\n    @Column()\n    createdAt: Date\n\n    @Column()\n    updatedAt: Date\n\n    @Column()\n    email: string\n\n    @OneToMany(type => UserChannel)\n    userChannels: UserChannel[]\n}\n\n@Entity()\nexport class UserChannel {\n\n    @ManyToOne(type => User)\n    user!: User;\n\n    @Column({\xc2\xa0primary: true })\n    userId!: string;\n\n\n    @ManyToOne(type => Channel)\n    channel!: channel;\n\n    @Column({\xc2\xa0primary: true })\n    channelId!: string;\n}\n\n\n@Entity()\nexport class Channel {\n\n    @PrimaryColumn()\n    id: string\n\n    @Column()\n    createdAt: Date\n\n    @Column()\n    updatedAt: Date\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n