乐闻世界logo
搜索文章和话题

What are the types of associations in GORM?

3月6日 21:37

GORM supports four main types of associations, each with its specific use cases and configuration methods:

1. Belongs To

Definition: A model belongs to another model, with the foreign key in the current model.

Example: User belongs to a department

go
type Department struct { ID uint Name string } type User struct { gorm.Model Name string DepartmentID uint Department Department `gorm:"foreignKey:DepartmentID"` } // Usage var user User db.Preload("Department").First(&user, 1)

Features:

  • Foreign key in the child model
  • The "many" side of a one-to-many relationship
  • Use foreignKey tag to specify the foreign key field

2. Has One

Definition: A model has one associated model, with the foreign key in the associated model.

Example: User has one credit card

go
type CreditCard struct { gorm.Model Number string UserID uint User User `gorm:"foreignKey:UserID"` } type User struct { gorm.Model Name string CreditCard CreditCard } // Usage var user User db.Preload("CreditCard").First(&user, 1)

Features:

  • Foreign key in the associated model
  • One-to-one relationship
  • Usually used for strong association scenarios

3. Has Many

Definition: A model has multiple associated models, with the foreign key in the associated models.

Example: User has multiple orders

go
type Order struct { gorm.Model UserID uint Amount float64 User User `gorm:"foreignKey:UserID"` } type User struct { gorm.Model Name string Orders []Order } // Usage var user User db.Preload("Orders").First(&user, 1) // Conditional preload db.Preload("Orders", "amount > ?", 100).First(&user, 1)

Features:

  • Foreign key in the associated model
  • One-to-many relationship
  • Most commonly used association type

4. Many To Many

Definition: A many-to-many relationship between two models, implemented through an intermediate table (join table).

Example: Many-to-many relationship between users and roles

go
type User struct { gorm.Model Name string Roles []Role `gorm:"many2many:user_roles;"` } type Role struct { gorm.Model Name string Users []User `gorm:"many2many:user_roles;"` } // Usage var user User db.Preload("Roles").First(&user, 1) // Add association db.Model(&user).Association("Roles").Append(&Role{Name: "Admin"}) // Delete association db.Model(&user).Association("Roles").Delete(&Role{Name: "Admin"}) // Replace association db.Model(&user).Association("Roles").Replace(&Role{Name: "User"}) // Clear association db.Model(&user).Association("Roles").Clear() // Count count := db.Model(&user).Association("Roles").Count()

Features:

  • Requires an intermediate table (join table)
  • Default join table name: table1_table2
  • Can customize join table name and fields

Custom Association Configuration

Custom foreign key

go
type User struct { gorm.Model CreditCards []CreditCard `gorm:"foreignKey:UserRefer"` } type CreditCard struct { gorm.Model Number string UserRefer uint }

Custom reference key

go
type User struct { gorm.Model Name string `gorm:"index"` CreditCard CreditCard `gorm:"foreignKey:UserName;references:Name"` } type CreditCard struct { gorm.Model Number string UserName string }

Custom many-to-many join table

go
type User struct { gorm.Model Roles []Role `gorm:"many2many:user_roles;joinForeignKey:UserID;joinReferences:RoleID"` } type Role struct { gorm.Model Name string Users []User `gorm:"many2many:user_roles;"` }

Preloading

Preloading is used to solve the N+1 query problem:

go
// Basic preload db.Preload("Orders").Find(&users) // Nested preload db.Preload("Orders.Items").Find(&users) // Conditional preload db.Preload("Orders", "status = ?", "completed").Find(&users) // Multiple preloads db.Preload("Orders").Preload("CreditCard").Find(&users)

Association Operations

Association API

go
// Find associations var roles []Role db.Model(&user).Association("Roles").Find(&roles) // Add association db.Model(&user).Association("Roles").Append(&Role{Name: "Admin"}) // Delete association db.Model(&user).Association("Roles").Delete(&Role{Name: "Admin"}) // Replace association db.Model(&user).Association("Roles").Replace([]Role{role1, role2}) // Clear association db.Model(&user).Association("Roles").Clear() // Count count := db.Model(&user).Association("Roles").Count()

Notes

  1. Foreign key naming: GORM defaults to using {associated model name}ID as the foreign key name
  2. Performance optimization: Use preloading reasonably to avoid N+1 queries
  3. Cascade delete: By default, deleting the primary record does not delete associated records, manual configuration is required
  4. Soft delete: GORM supports soft delete, pay attention to soft deleted records in association queries
  5. Transactions: Complex association operations are recommended to be executed in transactions
标签:Gorm