Gorm: How to properly apply updates to associations

Created on 18 Sep 2020  ·  11Comments  ·  Source: go-gorm/gorm

Your Question

Some code to handle updates that worked in GORM 1 has stopped working since the update, and I'm not sure why. It appears using Save only applies updates to the parent resource, and none of its associations.

Consider the following model:

type Car struct {
    ID        int
    Kind      string
    Value     float32
    PersonID  int
}
type Person struct {
    ID      int
    Name    string
    Car     Car     `gorm:"foreignkey:PersonID;"`
}

The following code creates an instance of Person, then modifies a few of its fields, and then performs a Save on the updated struct. However, after retrieving the updated resource, only the parent has been properly updated. The child remains unchanged

person := &Person{Name: "Jinzhu", Car: Car{Kind: "Audi", Value: 10000}}
db.Create(person)

id := person.ID

person.Car.Value = 9000
person.Name = "Jinzhu 2"
db.Save(person)

updatedPerson := &Person{}
db.Preload(clause.Associations).Take(updatedPerson, "id = ?", id)

fmt.Println(updatedPerson.Name == person.Name)              // TRUE
fmt.Println(updatedPerson.Car.Value == person.Car.Value)    // FALSE

The SQL Generated upon calling Save is as follows:

INSERT INTO "cars" ("kind","value","person_id","id") VALUES ('Audi',9000.000000,1,1) ON CONFLICT ("id") DO UPDATE SET "person_id"="excluded"."person_id" RETURNING "id";
UPDATE "people" SET "name"='Jinzhu 2' WHERE "id" = 1;

When I execute the first SQL statement directly in my PostgreSQL database, no changes get applied to the cars row.

The document you expected this should be explained


Update

Expected answer


Is there something I need to do differently to get the update on the child to work, or has something changed in GORM 2?

question

Most helpful comment

Hi @Robbie-Perry @rifqi12 @ocomsoft

DB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&user)

Will save all fields of associations, thank you for your report.

All 11 comments

I had the same issue - I posted a question on StackOverflow here https://stackoverflow.com/questions/63933736/gorm-association-not-updating hope this helps.

Hi @ocomsoft @Robbie-Perry

GORM V2 switched to use upsert to save associations, so save changed fields won't works in V2. (to avoid save uncompleted associations to protect your data)

https://gorm.io/docs/associations.html#Auto-Create-Update

image

But forgot to mention that in the breaking changes log, will update it.

Thank you.

@jinzhu Ok, thanks for the reply. Is there any way of working around this?

Could there be an option to change it so they are updated? Otherwise we have to update them twice

Would suggest you to write code like:

db.Model(&person.Car).Update("Value", 9000)
db.Model(&person).Updates(Person{Name: "Jinzhu 2"})

db.Model(&person).Updates(map[string]interface{}{"Name": "Jinzhu 2"})

This will have less code and better performance, and GORM will update person.Car.Value and person.Name's value to the correct one.

@jinzhu Thanks for your reply. But that doesn't work for me because my use case is a REST API Where I need to ensure the entire JSON tree is updated. In my case I am also talking about Many to Many so I would need to save the root object then also save each association object for each association to ensure all the data is updated in the database. Therefore doing more database calls. My example (https://stackoverflow.com/questions/63933736/gorm-association-not-updating) was just to show the problem it's not how I am using GORM.

The way I see it at the moment it only Inserts New associated 'objects' and doesn't update them. Maybe the documentation needs to change to make this clear. I expected it to save all the objects.

Thanks for the suggestion @jinzhu, i had the issue where the join table from many2many associations aren't updated.
It seem we can't do:

db.Model(&person.Friends).Update(newFriendsSlice)

Is there any workaround for this case?

@jinzhu Thanks for the reply, but I'm in a similar situation to @ocomsoft , except I have to perform updates on an arbitrary data type, and have no way of knowing what the relations are. As a result, I'm not sure if GORM is any longer viable for my usecase.

Hi @Robbie-Perry @rifqi12 @ocomsoft

DB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&user)

Will save all fields of associations, thank you for your report.

@jinzhu Thank you very much for this! You just earned yourself a donation

Hi @Robbie-Perry @rifqi12 @ocomsoft

DB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&user)

Will save all fields of associations, thank you for your report.

You are a life saver @jinzhu .. ❤️

Was this page helpful?
0 / 5 - 0 ratings

Related issues

izouxv picture izouxv  ·  3Comments

easonlin404 picture easonlin404  ·  3Comments

pjebs picture pjebs  ·  3Comments

satb picture satb  ·  3Comments

superwf picture superwf  ·  3Comments