英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论