Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
166 views
in Technique[技术] by (71.8m points)

GORM: Updating inserts nested data instead of modifying

When I update a nested model, GORM will not update the children, it inserts new children and updates the parent.

I have a fairly simple data model I have a base model

type Base struct {
    ID        string  `gorm:"primaryKey;unique;type:uuid;default:uuid_generate_v4();" json:"id"`
    CreatedAt time.Time `gorm:"type:timestamp without time zone;not null;"`
    UpdatedAt time.Time `gorm:"type:timestamp without time zone;not null;"`
}

**I only have the unique tag in there as Jinzhu (Gorm coder), suggested to add it. I thought having primary key was enough.

I have a Customer Model

type ClientCustomer struct {
    Base
    Name          string
    Address       string
    Lat           float32
    Lon           float32
    ClientID      string `gorm:"type:uuid"`
    Contacts      []CustomerContact
}

I have a contact model

type CustomerContact struct {
    Base
    Name             string `gorm:"not null"`
    Email            string
    Phone            string
    ContactTypeID    uint
    ClientCustomerID string `gorm:"type:uuid"`
    
}

A customer has a one-to-many relationship with contacts. When I want to update a customer/customer contact, GORM ends up inserting a new contact and updates the customer. I would expect GORM to update both models.

This is the json I am sending:

{
    "id": "a375380a-0450-4670-8e23-9dc1d08249cd",
    "clientId": "d97a96ca-6b05-423a-814c-7c4ba2a5ebe4",
    "name": "Customer Name",
    "address": "Customer address",
    "lat": 0,
    "lon": 0,
    "sites": [],
    "customerContacts": [
        {
            "id": "39e78040-92a1-4834-aff6-ff64661c5d65",
            "name": "Jessica2",
            "email": "[email protected]",
            "phone": "555555555",
            "contactType": 1,
            "customerId": "a375380a-0450-4670-8e23-9dc1d08249cd",
            "clientId": "d97a96ca-6b05-423a-814c-7c4ba2a5ebe4"
        }
    ]
}

My code to update is:

DB.Debug().Updates(updateData) => updateDate is a customer

I have also tried the following:

DB.Debug().Save(updateData)
db.Session(&gorm.Session{FullSaveAssociations: true}).Updates(updateData)

It always inserts new children In looking at my table structure in postgres, its exactly what it should be. There is a foreign key from contacts to customer

I am running out of ideas.

Here is the output from GORM:

[1.319ms] [rows:1] INSERT INTO "customer_contacts" ("name","email","phone","contact_type_id","client_customer_id","created_at","updated_at","doppl_client_id","id") VALUES ('Jessica2','[email protected]','555555555',1,'a375380a-0450-4670-8e23-9dc1d08249cd','2021-01-26 18:12:05.744','2021-01-26 18:12:05.744','d97a96ca-6b05-423a-814c-7c4ba2a5ebe4','d749018f-5484-4308-a60d-3ef86a896a6b') ON CONFLICT ("id") DO UPDATE SET "client_customer_id"="excluded"."client_customer_id" RETURNING "id"


2021/01/26 18:12:05 /go/src/app/pkg/providers/gormRepository.go:120

[3.543ms] [rows:1] UPDATE "client_customers" SET "name"='Customer Name',"address"='Customer address',"doppl_client_id"='d97a96ca-6b05-423a-814c-7c4ba2a5ebe4',"updated_at"='2021-01-26 18:12:05.743' WHERE "id" = 'a375380a-0450-4670-8e23-9dc1d08249cd'
question from:https://stackoverflow.com/questions/65907002/gorm-updating-inserts-nested-data-instead-of-modifying

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Gorm is actually running an upsert. Have a look at the full query that gorm is running:

INSERT INTO "customer_contacts" ("name","email","phone","contact_type_id","client_customer_id",
    "created_at","updated_at","doppl_client_id","id") 
VALUES ('Jessica2','[email protected]','555555555',1,'a375380a-0450-4670-8e23-9dc1d08249cd',
    '2021-01-26 18:12:05.744','2021-01-26 18:12:05.744','d97a96ca-6b05-423a-814c-7c4ba2a5ebe4',
    'd749018f-5484-4308-a60d-3ef86a896a6b')
ON CONFLICT ("id") DO UPDATE SET "client_customer_id"="excluded"."client_customer_id" 
RETURNING "id"

(this must be the query for the Updates call without the FullSaveAssociation: true)

It has an ON CONFLICT clause so that when the primary key already exists, instead of inserting it updates the client_customer_id of the customer_contact record. You'll find that with FullSaveAssociation: true this changes to updating all the fields.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...