typeorm: Update not work for ManyToMany relationship
Issue type:
[ ] question [ x] bug report [ ] feature request [ ] documentation issue
Database system/driver:
[ ] cordova
[ ] mongodb
[ ] mssql
[ ] mysql / mariadb
[ ] oracle
[x ] postgres
[ ] sqlite
[ ] sqljs
[ ] react-native
[ ] expo
TypeORM version:
[x ] latest
[ ] @next
[ ] 0.x.x (or put your version here)
Steps to reproduce or a small repository showing the problem:
@Entity()
export class Image {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
isRemoved: boolean = false;
}
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToMany(type => Image, { eager: true, cascade: ["update"] })
@JoinTable()
images: Image[];
}
const img1 = new Image();
img1.name = "kids";
await connection.manager.save(img1);
const img2 = new Image();
img2.name = "future";
await connection.manager.save(img2);
const img3 = new Image();
img3.name = "changed";
await connection.manager.save(img3);
let post = new Post();
post.title = "about kids";
post.images = [img1, img2];
post = await connection.manager.save(post);
const postdata: any = await connection.getRepository(Post).findOne(post.id);
expect(postdata).to.not.be.empty;
expect(postdata.images[0].id).to.be.equal(1);
expect(postdata.images[1].id).to.be.equal(2);
let updjson = {"id": post.id, "title": "about other kids", "images": [{"id": img3.id, "name": img3.name}]};
// const updpost = connection.getRepository<Post>(Post).create(updjson);
// await connection.getRepository(Post).save(updjson);
await connection.getRepository(Post).update(post.id, updjson);
const postdata2: any = await connection.getRepository(Post).findOne(post.id);
expect(postdata2).to.not.be.empty;
expect(postdata2.images).to.be.an("array").with.length(1);
expect(postdata2.images[0].id).to.be.equal(1);
Given example crashes with QueryFailedError: column “postId” of relation “post” does not exist
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 48
- Comments: 25 (4 by maintainers)
Hi, also faced with this issue. I’ve looked into the code and found out that inserting relational data in
many-to-manycase is not implemented forrepository.updateoperations, but you can update entities withmany-to-manyrelations viarepository.save, so your example should works after small modification:In API says:
This issue is open since many years, kindly provide some update if it is something work in progress or hasn’t started yet? It seems to be occurring for multiple databases and not just limited to PostgreSQL.
Please give bugs priority over new features. We are waiting for this to be fixed for so long.
Not even a single update about this issue, it still on with 0.2.29, and in fact the workaround would be use the repository.save() method
Also bumped into this issue. Using
save()instead ofupdate()works for me too, andupdatedAtworks as usual.update()should definitely be updatingUpdateDateColumns, if someone can make a reproducible test please send in a new issue.update()is meant to be a high performanceUPDATEquery at the cost of not doing all the magic persistence stuff ofsave(). Unfortunately Many-to-Many relations become a bit more difficult to deal with because of that, since they make their own junction table that you don’t have direct access to.The solution to that is either to make your own junction table (and use a Many-to-One on each side), or to use
RelationQueryBuilder.add().Using
.save()does not seem to update theupdatedAt(UpdateDateColumn) attribute 🤔I replaced :
await this.shopService.update(id, updateShopDto )with:and it worked! Though I hope to find a smarter solution than this
You can make new newPost = this.await connection.getRepository(Post).create(); newPost.id = post.id newPost.images = [{“id”: img3.id, “name”: img3.name}] this.await connection.getRepository(Post).save(newPost);
it may work.
I am also getting this exact same problem when using update.
Absolutely it should!
Also, not exclusive to postgres, got into this problem with MySQL too. Doesn’t seem to be driver related then.
Was having the same problem because it fails silently and most of the replies here didn’t work. It was driving me absolutely nuts. After some research I found this method. Using a User as an example entity.
This will delete all entries in the junction table that match the provided existing user and replace for the new ones. It’s relatively fast but probably won’t save you from executing two queries. Please note you’ll still have to call update/save to change the existingUser WITHOUT the many-to-many portion of the DTO. To circle this one, I’ve made an if that checks if a “tasks” update is present in the DTO and after running the query above I call
delete dto.tasksand close the if. TL;DR: one query to update the many-to-many column, another for the rest. It’s a dangerous problem indeed and to make things worse it’s a silent one.Still get this issue, after some workaround, I used to use this way to kinda solve the issue temporarily (probably). For example for the user and role many-to-many relations.
And then I used DTO for the update process such:
Finally, the update process only uses the
save()method:There’s still room for improvements but using this approach is kinda simple for me.