简体   繁体   中英

Update a many-to-many relationship with TypeORM

I am having issues updating a entity that has a many-to-many reln, curious if I am doing something wrong, or more specifically what is the right way to do this

Consider the following entities...

@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[];

In my code I find the node and then try to update it and save like so...

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

But alas, the subjects are not saved on the note.

What is the right way to do this?

Thanks!

In my case Im trying to update an existing relation but that gives me a unique key violation because the relation already exists, so I first need to remove all existing relationships and then add the relationships of my updated user:

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)
};

So the following got it working for me:

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

Though, I still kind of feel that the repo.save() method should work

By default cascading is set to false, you can enable this as follows:

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

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

Check this answer: How to update an entity with relations using QueryBuilder in TypeORM

It worked for me.

...
note.subjects = foundSubjects;
const toUpdate = await noteRepo.preload(note)
noteRepo.save(toUpdate);

Don't forget the await , is missing in the answer, or is somthing to do with eager: true ... I'm not sure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM