How to make foreign key using gorm

Viewed 20065

I have those two models:

User model:

type User struct {
    DBBase
    Email    string `gorm:"column:email" json:"email"`
    Password string `gorm:"column:password" json:"-"`
}

func (User) TableName() string {
    return "t_user"
}

User info model:

type UserInfo struct {
    User      User   `gorm:"foreignkey:u_id;association_foreignkey:id"`
    UID       uint   `gorm:"column:u_id" json:"-"`
    FirstName string `gorm:"column:first_name" json:"first_name"`
    LastName  string `gorm:"column:last_name" json:"last_name"`
    Phone     string `gorm:"column:phone" json:"phone"`
    Address   string `gorm:"column:address" json:"address"`
}

func (UserInfo) TableName() string {
    return "t_user_info"
}

and I want to make UID related to the id of the user table.

this is the function that creates the user:

func (dao *AuthDAO) Register(rs app.RequestScope, user *models.User, userInfo *models.UserInfo) (userErr error, userInfoErr error) {
    createUser := rs.Db().Create(&user)
    userInfo.UID = user.ID
    createUserInfo := rs.Db().Create(&userInfo)

    return createUser.Error, createUserInfo.Error
}

I did try what gorm wrote on the documentation, but without success: http://doc.gorm.io/associations.html

5 Answers

I found the following code correctly created the foreign key without having to do any custom migration code; just the usual AutoMigrate.


type Account struct {
    ID uint `gorm:"primary_key"`
}

type Transaction struct {
    ID        uint `gorm:"primary_key"`
    AccountID uint
    Account   Account `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}

I am using "Gorm 2.0" which is a dependency of gorm.io/gorm v1.23.3.

Read about the belongs to relationship in https://gorm.io/docs/belongs_to.html Also, there's a good example here: https://medium.com/@the.hasham.ali/how-to-use-uuid-key-type-with-gorm-cc00d4ec7100

// User is the model for the user table.
type User struct {
 Base
 SomeFlag bool    `gorm:"column:some_flag;not null;default:true"`
 Profile  Profile
}// Profile is the model for the profile table.
type Profile struct {
 Base
 Name   string    `gorm:"column:name;size:128;not null;"`
 UserID uuid.UUID `gorm:"type:uuid;column:user_foreign_key;not null;"`
}

We can add foreign key constraints in the latest version using CreateConstraint.

Example: Suppose we have two entity

type User struct {
  gorm.Model
  CreditCards []CreditCard
}

type CreditCard struct {
  gorm.Model
  Number string
  UserID uint
}

Now create database foreign key for user & credit_cards

db.Migrator().CreateConstraint(&User{}, "CreditCards")
db.Migrator().CreateConstraint(&User{}, "fk_users_credit_cards")

which translates to the following SQL code for Postgres:

ALTER TABLE `credit_cards` ADD CONSTRAINT `fk_users_credit_cards` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)

Referrence:

For recent release of Gorm i.e. 1.21.xIf you have a one to one mapping of fields and not have parent to child mapping, here is what you will do

type BaseConfig struct {
    ID         uuid.UUID       `gorm:"primary_key" json:"id"`
}

type Ledger struct { 
    BaseConfigId        uuid.UUID       `json:"base_config_id"`
    BaseConfig BaseConfig               `gorm:"column:base_config_id;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`

}

In Migration script you will need to follow as per docs

WriteClient.Migrator().CreateConstraint(&models.BaseConfig{}, "Ledgers")
WriteClient.Migrator().CreateConstraint(&models.BaseConfig{}, "fk_base_configs_id")

I feel the tripping point is the missing documentation for how to associate. Some juggling around could be there to figure it out, so hope my answer saves some time.

Related