1

I have these 2 models:

type Residue struct {
    ID           int
    Name         string

    Categories []*ResidueCategory `gorm:"many2many:residue_residue_categories"`
}

type ResidueCategory struct {
    ID           int
    Name         string

    Residues []*Residue `gorm:"many2many:residue_residue_categories"`
}

I already have the residue_residue_categories table. But the columns are:

  • id (int)
  • residueId (int, foreign key)
  • residueCategoryId (int, foreign key)

And I want to do an append association like:

db.Model(&data).Association("Categories").Append(CategoriesData)

But SQL generate is:

INSERT INTO "residue_residue_categories" ("residue_id","residue_category_id") VALUES (49,4) ON CONFLICT DO NOTHING

As you can see, the columns' names in the insert SQL are not correct.

I've already tried to configure additional fields like:

Categories []*ResidueCategory `gorm:"many2many:residue_residue_categories;foreignkey:residueId;association_foreignkey:residueCategoryId"`
Residues []*Residue `gorm:"many2many:residue_residue_categories;association_foreignkey:residueId;foreignkey:residueCategoryId"`

But weirdly, GORM throws: invalid foreign key: residueId in a simple GetById (before the append relation). How I can configure this relation with these custom columns' names?

Matheus
  • 301
  • 3
  • 16
  • Please see answer to similar question [here](https://stackoverflow.com/a/75766167/21985642) – Sapan V Jun 20 '23 at 16:51
  • I saw that, but even create a model ResidueResidueCateogory, I could not handle successfully this relation append. A similar error was throw `invalid foreign key` – Matheus Jun 20 '23 at 16:59

1 Answers1

1

I put together a small example to try to figure out your issue. First, let me share the code, then I'll walk you through all of the relevant sections of the code.

package main

import (
    "fmt"

    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

type Residue struct {
    ID   int
    Name string

    ResidueResidueCategories []*ResidueResidueCategory
}

type ResidueResidueCategory struct {
    ID                int `gorm:"primaryKey"`
    ResidueCategoryId int `gorm:"column:residueCategoryId"`
    ResidueId         int `gorm:"column:residueId"`
}

type ResidueCategory struct {
    ID   int
    Name string

    ResidueResidueCategories []*ResidueResidueCategory
}

func main() {
    dsn := "host=localhost port=54322 user=postgres password=postgres dbname=postgres sslmode=disable"
    db, err := gorm.Open(postgres.Open(dsn))
    if err != nil {
        panic(err)
    }

    db.AutoMigrate(&Residue{}, &ResidueCategory{}, &ResidueResidueCategory{})

    // insert into parent tables
    db.Create(&Residue{ID: 1, Name: "residue 1"})
    db.Create(&ResidueCategory{ID: 1, Name: "category 1"})

    // insert into join table
    db.Debug().Model(&Residue{ID: 1}).Association("ResidueResidueCategories").Append(&ResidueResidueCategory{ResidueCategoryId: 1, ResidueId: 1})

    // fetch data
    var joinTableRecords []ResidueResidueCategory
    if err := db.Model(&ResidueResidueCategory{}).Find(&joinTableRecords).Error; err != nil {
        panic(err)
    }
    for _, v := range joinTableRecords {
        fmt.Println(v)
    }
}

Now, let's take a closer look at each part.
The structs' definitions have been changed a quite. I've to insert the definition for the join table and override its columns names.

Please note that I added the definition only for completeness, you can ignore it if your join table is already present in the DB.

The other change is how I insert the data into the DB. First, you've to insert the data in the parent tables (residues and residue_categories), then you can add the association within the residue_residue_categories join table.
I added the Debug() method to show you the SQL statement sent to the DB even if you run the code without attaching the debugger.

To barely focus on the logic, I hard-coded some values within the program but it should be easy to adjust to your own logic.
Let me know if this solves your issue, thanks!

ossan
  • 1,665
  • 4
  • 10
  • 1
    Thank you for your answer, but I think this will not solve my problem. When you do the `Append` the generated SQL will use the wrong columns names – Matheus Jun 21 '23 at 15:55
  • Sorry for the misunderstanding. I've just updated my answer with the requested code. Let me know, thanks! – ossan Jun 22 '23 at 08:13