【问题标题】:Update a many-to-many relationship with TypeORM使用 TypeORM 更新多对多关系
【发布时间】:2021-03-11 17:47:54
【问题描述】:

我在更新具有多对多 reln 的实体时遇到问题,好奇我是否做错了什么,或者更具体地说,这样做的正确方法是什么

考虑以下实体...

@Entity
class Subject
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;

  @ManyToMany(() => Note, note => note.subjects)
  @JoinTable()
  notes: Note[];

  ...

@Entity()
export class Note {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @ManyToMany(() => Subject, (subject: Subject) => subject.notes)
  subjects: Subject[];

在我的代码中,我找到了节点,然后尝试更新它并像这样保存......

const note = await noteRepo.findOneOrFail(noteId);
const foundSubjects = await subjectRepo.findByIds(Array.from(subjectIds));
note.subjects = foundSubjects;
noteRepo.save(note);

但是很可惜,主题并没有保存在笔记上。

这样做的正确方法是什么?

谢谢!

【问题讨论】:

    标签: javascript node.js typeorm


    【解决方案1】:

    在我的情况下,我尝试更新现有关系,但这给了我一个唯一键违规,因为该关系已经存在,所以我首先需要删除所有现有关系,然后添加我更新后的用户的关系:

    export const updateUser = async (user: User): Promise<User | undefined> => {
        /**
         * Get the actual relationships of that user.
         */
        const actualRelationships = await getRepository(User)
            .createQueryBuilder()
            .relation(User, 'roles')
            .of(user).loadMany();
    
        /**
         * Add new relationships of the user, and delete the old relationships.
         */
        await getRepository(User)
            .createQueryBuilder()
            .relation(User, 'roles')
            .of(user)
            .addAndRemove(user.roles, actualRelationships);
    
        /**
         * Update only the table USER.
         */
        await getRepository(User)
            .createQueryBuilder()
            .update()
            .set({
                name: user.name,
                username: user.username,
                active: user.active
            })
            .where('id = :id', {id: user.id})
            .execute();
    
        /**
         * Return the updated user
         */
        return await getUser(user.id, true, true)
    };
    

    【讨论】:

    • 最好将所有这些操作放在一个事务中
    【解决方案2】:

    所以以下内容对我有用:

      subjectIds.forEach(async id => {
      await connection
        .createQueryBuilder()
        .relation(Note, 'subjects')
        .of(note)
        .add(id);
    });
    

    虽然,我还是觉得 repo.save() 方法应该工作

    【讨论】:

    • 那么,这是否意味着如果要进行更多更改,我们必须编写单独的查询,例如 Nestor Perez 的回答?
    • 您不需要forEach.add 也接受一个 ID 数组。应该稍微简化一下代码。
    【解决方案3】:

    默认级联设置为false,您可以按如下方式启用:

    @Entity()
    export class Note {
    @PrimaryGeneratedColumn('uuid')
    id: string;
    
    @ManyToMany(() => Subject, (subject: Subject) => subject.notes, { cascade: true })
    subjects: Subject[];
    

    【讨论】:

    • note.subjects = [{id:1}, {id:2}]; noteRepo.save(note); 然后就可以工作了。
    • 这适用于添加新主题,但是如果我们想用其他 id 替换这些 id 怎么办?我们必须使用.relation().of().addAndRemove()吗?
    • .save() 不起作用,即使您尝试从多对多联结表中删除项目。
    猜你喜欢
    • 2020-06-29
    • 2020-09-27
    • 1970-01-01
    • 2020-09-01
    • 2020-12-03
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    相关资源
    最近更新 更多