Home > Software design >  GORM Error on insert or update on table violates foreign key constraint
GORM Error on insert or update on table violates foreign key constraint

Time:08-24

I have the following set of GORM models, with 2 orders of one-to-many relations:

type Order struct {
    ID       string  `gorm:"column:id"`
    ClientID string  `gorm:"primaryKey;column:client_id"`
    Name     string  `gorm:"column:name"`
    Albums   []Album `gorm:"foreignKey:RequestClientID"`
}

type Album struct {
    AlbumID         string    `gorm:"primaryKey;column:album_id"`
    RequestClientID string    `gorm:"foreignKey:ClientID;column:request_client_id"`
    Pictures        []Picture `gorm:"foreignKey:AlbumID"`
}

type Picture struct {
    PictureID   string `gorm:"primaryKey;column:picture_id"`
    AlbumID     string `gorm:"foreignKey:AlbumID;column:album_id"`
    Description string `gorm:"column:description"`
}

When I attempt to insert data as follows, I get the error pq: insert or update on table "albums" violates foreign key constraint "fk_orders_albums".

test := Order{
    ID:       "abc",
    ClientID: "client1",
    Name:     "Roy",
    Albums: []Album{
        {
            AlbumID: "al_1",
            Pictures: []Picture{
                {
                    PictureID:   "pic_1",
                    Description: "test pic",
                },
            },
        },
    },
}

gormDB.Save(&test)

I followed the solution on this similar question, but can't seem to get it to work: Golang: Gorm Error on insert or update on table violates foreign key contraint

CodePudding user response:

Based on your entity model, Your schema would be like this:

  • Orders table is parent table, didn't depend to any table
  • Albums table has foreign key request_client_id which refer to orders table column client_id
  • Picture table has foreign key album_id which is refer to albums table column album_id

Based on my exploration in gorm documentation here, object in struct will be examine as first association. so, your struct will execute insert to albums first which it violate foreign key schema (expect: insert to orders table should be executed before albums).

But if you want to force using your schema, you can use gorm Association feature. Here is the idea of using Association:

Expected Query in high level:

  • Insert to orders table
  • Insert to albums table
  • Insert to pictures table

Association Ideas:

  • Let Albums field value in Orders struct empty
  • Append Association Albums to Orders model
  • Since there have another association in Albums, use configuration FullSaveAssociation

Here is the following code:

picture := []Picture{
    {
        PictureID:   "pic_1",
        Description: "test pic",
    },
}
albums := []Album{
    {
        ID:              "al_1",
        Pictures:        picture,
        RequestClientID: "",
    },
}
orders := Order{
    ID:       "abc",
    ClientID: "client1",
    Name:     "Roy",
}
if err := gormDB.Save(orders).Error; err != nil {
    return
}
if err := gormDB.Session(&gorm.Session{FullSaveAssociations: true}).Model(&orders).Association("Albums").Append(albums); err != nil {
    return
}

Full code could be found here:

CodePudding user response:

Came across the solution I was looking for while looking into the great answer @giyuu provided. Since I had not saved the item before, I needed to use GORM's Create method:

err = gormDB.Create(&test).Error

Then, when I want to perform an update on any of these values, I use the Save method, with FullSaveAssociations enabled:

err = gormDB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&test).Error
  • Related