如何使用TypeORM更新ManyToMany关系?

huangapple go评论74阅读模式
英文:

How to update a ManyToMany relation with TypeORM?

问题

I have a candidate entity with many "ManyToMany" relations, I need to create an update function for this entity.
Here is my candidate entity:

@Entity()
export class Candidate {
    @PrimaryGeneratedColumn()
    id: number;
    
    ...

    @ManyToMany(() => Language, { nullable: true })
    @JoinTable()
    languages: Language[];

    @ManyToMany(() => Tool, { nullable: true })
    @JoinTable()
    tools: Tool[];

    @ManyToMany(() => ActivityArea, { nullable: true })
    @JoinTable()
    activity_areas: ActivityArea[];

    ...

    @Column({ nullable: true })
    desired_starting_date: string;

    ...
}

Language entity (the others are similar):

@Entity()
export class Language {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({unique: true})
    name: string;
}

I tried to use the update function of typeORM:

async update(id: number, updateCandidateDto: UpdateCandidateDto) {
    try {
        const candidate = this.generateaCandidate(updateCandidateDto); // this is the new value of candidate

        return await this.candidateRepository.update({
            id
        }, {
            languages: candidate.languages,
            tools: candidate.tools,
            activity_areas: candidate.activity_areas,
            desired_starting_date: candidate.desired_starting_date
        });
    } catch (error) {
        throw new HttpException(error.detail, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

But I got the following error: Error: Cannot query across many-to-many for property tools

I check the following post before posting this one:
https://stackoverflow.com/questions/54137386/update-a-many-to-many-relationship-with-typeorm
https://stackoverflow.com/questions/73507196/typeorm-nestjs-update-manytomany-relation-when-using-querybuilder-violates-not
https://stackoverflow.com/questions/49596061/typeorm-updating-entity-table

Can you help me to build an update function that allows me to update several ManyToMany parameters?

英文:

I have a candidate entity with many "ManyToMany" relations, I need to create an update function for this entity.
Here is my candidate entity:

@Entity()
export class Candidate {
	@PrimaryGeneratedColumn()
		id: number;
	
	...

	@ManyToMany(() => Language, { nullable: true })
	@JoinTable()
		languages: Language[];

	@ManyToMany(() => Tool, { nullable: true })
	@JoinTable()
		tools: Tool[];

	@ManyToMany(() => ActivityArea, { nullable: true })
	@JoinTable()
		activity_areas: ActivityArea[];

	...

	@Column({ nullable: true })
		desired_starting_date: string;

	...
}

Language entity (the others are similar):

@Entity()
export class Language {
	@PrimaryGeneratedColumn()
		id: number;

	@Column({unique: true})
		name: string;
}

I tried to use the update function of typeORM :

async update(id: number, updateCandidateDto: UpdateCandidateDto) {
	try {
		const candidate = this.generateaCandidate(updateCandidateDto); // this is the new value of candidate

		return await this.candidateRepository.update({
			id
		}, {
			languages: candidate.languages,
			tools: candidate.tools,
			activity_areas: candidate.activity_areas,
			desired_starting_date: candidate.desired_starting_date
		});
	} catch (error) {
		throw new HttpException(error.detail, HttpStatus.INTERNAL_SERVER_ERROR);
	}
}

But I got the following error : Error: Cannot query across many-to-many for property tools

I check the following post before posting this one:
https://stackoverflow.com/questions/54137386/update-a-many-to-many-relationship-with-typeorm
https://stackoverflow.com/questions/73507196/typeorm-nestjs-update-manytomany-relation-when-using-querybuilder-violates-not
https://stackoverflow.com/questions/49596061/typeorm-updating-entity-table

Can you help me to build an update function that allows me to update several ManyToMany parameters?

答案1

得分: 0

我终于找到了一种方法来做到这一点:

async update(id: number, updateCandidateDto: UpdateCandidateDto) {
    try {
        const new_candidate = await this.generateCandidate(updateCandidateDto);

        for (const prop in new_candidate) {
            if (typeof new_candidate[prop] == 'object') {
                const actualRelationships = await this.candidateRepository
                    .createQueryBuilder()
                    .relation(Candidate, prop)
                    .of(id)
                    .loadMany();

                await this.candidateRepository
                    .createQueryBuilder()
                    .relation(Candidate, prop)
                    .of(id)
                    .addAndRemove(new_candidate[prop], actualRelationships);
            } else {
                const json = JSON.parse(`{ "${prop}" : "${new_candidate[prop]}" }`);

                this.candidateRepository
                    .createQueryBuilder()
                    .update(Candidate)
                    .set(json)
                    .where('id = :id', {id: id})
                    .execute();
            }
        }

        return await this.findOne(id);
    } catch (error) {
        console.error(error);
        throw new HttpException('Update failed', HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

我测试要修改的候选人的每个属性,如果属性的类型是'object',那么它意味着它是一个外键。在这种情况下,我从数据库中检索所有相关关系,并用新的关系替换它们。

这个解决方案有效,我会使用它,直到有更好的解决方案被提出。

英文:

I finaly found a way to did it :

async update(id: number, updateCandidateDto: UpdateCandidateDto) {
	try {
		const new_candidate = await this.generateCandidate(updateCandidateDto);

		for (const prop in new_candidate) {
			if (typeof new_candidate[prop] == 'object') {
				const actualRelationships = await this.candidateRepository
					.createQueryBuilder()
					.relation(Candidate, prop)
					.of(id)
					.loadMany();
				
				await this.candidateRepository
					.createQueryBuilder()
					.relation(Candidate, prop)
					.of(id)
					.addAndRemove(new_candidate[prop], actualRelationships);
			} else {
				const json = JSON.parse(`{ "${prop}" : "${new_candidate[prop]}" }`);
                    
                this.candidateRepository
                   .createQueryBuilder()
                   .update(Candidate)
                   .set(json)
                   .where('id = :id', {id: id})
.execute();
			}
		}

		return await this.findOne(id);
	} catch (error) {
		console.error(error);
		throw new HttpException('Update failed', HttpStatus.INTERNAL_SERVER_ERROR);
	}
}

I test each property of the candidate I want to modify, if the property is of type 'object' it means that it is a foreign key. In this case, I retrieve all its relations from the database and replace them with the new relations.

This solution works, I will use it until a better solution is proposed.

huangapple
  • 本文由 发表于 2023年3月15日 20:30:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75744712.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定