Skip to main content
A belongs to association sets up a many-to-one relationship. Each instance of the declaring model “belongs to” one instance of another model. The foreign key lives on the declaring model’s table.

Struct definition

Declare a belongs to association by embedding the associated struct and adding a foreign key field:
type User struct {
  gorm.Model
  Name string
}

type Profile struct {
  gorm.Model
  UserID int    // foreign key — references users.id
  User   User   // association
  Name   string
}
When GORM sees User User alongside UserID int, it automatically infers the belongs to relationship. The convention is <TypeName>ID.

Override the foreign key

Use the foreignKey tag to point to a different field on the declaring model:
type User struct {
  gorm.Model
  Name string
}

type Profile struct {
  gorm.Model
  UserRefer int
  User      User `gorm:"foreignKey:UserRefer"`
  Name      string
}

Override references

By default GORM uses the associated model’s primary key as the reference. Use references to point to a different field:
type User struct {
  gorm.Model
  Name   string
  Refer  string `gorm:"uniqueIndex"`
}

type Profile struct {
  gorm.Model
  Name      string
  UserRefer string
  User      User `gorm:"foreignKey:UserRefer;references:Refer"`
}
The referenced field must have a unique constraint so the database can enforce referential integrity.

Create with a BelongsTo association

When you create a record, GORM saves associated structs automatically if they have a zero-value primary key:
profile := Profile{
  Name: "jinzhu's profile",
  User: User{Name: "jinzhu"},
}
db.Create(&profile)
// INSERT INTO users (name) VALUES ('jinzhu');
// INSERT INTO profiles (name, user_id) VALUES ('jinzhu\'s profile', 1);
To associate with an existing user, set the foreign key directly:
profile := Profile{
  Name:   "jinzhu's profile",
  UserID: 1, // reference an existing user
}
db.Create(&profile)

Query with Preload

Use Preload to eagerly load a BelongsTo association in a single query pair:
var profiles []Profile
db.Preload("User").Find(&profiles)
// SELECT * FROM profiles;
// SELECT * FROM users WHERE id IN (1, 2, 3);
Load a single profile with its user:
var profile Profile
db.Preload("User").First(&profile, 1)

Conditional preload

Pass additional conditions to Preload to filter the associated records:
var profiles []Profile
db.Preload("User", "name = ?", "jinzhu").Find(&profiles)
// Only loads users where name = 'jinzhu'
Use a function for more complex conditions:
db.Preload("User", func(db *gorm.DB) *gorm.DB {
  return db.Where("name LIKE ?", "%jin%")
}).Find(&profiles)

Query with Joins

Use Joins to load the association with a SQL join instead of a separate query:
var profiles []Profile
db.Joins("User").Find(&profiles)
// SELECT profiles.*, users.id AS "User__id", users.name AS "User__name"
// FROM profiles LEFT JOIN users ON users.id = profiles.user_id;
Joins issues a single SQL statement. Preload issues two queries but works better when loading many rows because it avoids a Cartesian product.

Update a BelongsTo association

Update the foreign key field directly and save:
db.Model(&profile).Update("UserID", 2)
Or use Association mode to replace the associated record:
newUser := User{Name: "new owner"}
db.Model(&profile).Association("User").Replace(&newUser)

Constraints

GORM creates a database-level foreign key constraint when auto-migrating:
type Profile struct {
  gorm.Model
  UserID int
  User   User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}
Set OnDelete or OnUpdate to any SQL referential action: CASCADE, SET NULL, RESTRICT, NO ACTION.

Build docs developers (and LLMs) love