InfoSphere/GORM 中文版/ 返回书籍
Associations

Preloading (Eager Loading)

qianmoQqianmoQ· 更新于 2026-09-14· 阅读 12 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

Preload

GORM allows eager loading relations in other SQL with Preload, for example:

Generics API

type User struct {
  gorm.Model
  Username string
  Orders   []Order
}

type Order struct {
  gorm.Model
  UserID uint
  Price  float64
}



user, err := gorm.G[User](db).Preload("Order", nil).Find(ctx)





user, err = gorm.G[User](db).Preload("Orders", func(db gorm.PreloadBuilder) error {
  db.Order("orders.price DESC")
  return nil
}).Find(ctx)


Traditional API


db.Preload("Orders").Find(&users)



db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users)



Joins Preloading

Preload loads the association data in a separate query, Join Preload will loads association data using left join, for example:

Generics API

type User struct {
  gorm.Model
  Username string
  Order    Order
}

type Order struct {
  gorm.Model
  UserID uint
  Price  float64
}

users, err := gorm.G[User](db).Joins(clause.JoinTarget{Association: "Order"}, nil).Find(ctx)



users, err := gorm.G[User](db).Joins(
  clause.JoinTarget{Association: "Order"},
  func(db gorm.JoinBuilder, joinTable clause.Table, curTable clause.Table) error {
    db.Where(Order{Price: 1000})
    return nil
}).Find(ctx)

Traditional API

db.Joins("Company").Joins("Manager").Joins("Account").First(&user, 1)
db.Joins("Company").Joins("Manager").Joins("Account").First(&user, "users.name = ?", "jinzhu")
db.Joins("Company").Joins("Manager").Joins("Account").Find(&users, "users.id IN ?", []int{1,2,3,4,5})

Join with conditions

db.Joins("Company", DB.Where(&Company{Alive: true})).Find(&users)

Join nested model

db.Joins("Manager").Joins("Manager.Company").Find(&users)

NOTE Join Preload works with one-to-one relation, e.g: has one, belongs to

Preload All

clause.Associations can work with Preload similar like Select when creating/updating, you can use it to Preload all associations, for example:

type User struct {
  gorm.Model
  Name       string
  CompanyID  uint
  Company    Company
  Role       Role
  Orders     []Order
}

db.Preload(clause.Associations).Find(&users)

clause.Associations won’t preload nested associations, but you can use it with Nested Preloading together, e.g:

db.Preload("Orders.OrderItems.Product").Preload(clause.Associations).Find(&users)

Preload with conditions

GORM allows Preload associations with conditions, it works similar to Inline Conditions


db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)



db.Where("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)

Custom Preloading SQL

You are able to custom preloading SQL by passing in func(db *gorm.DB) *gorm.DB, for example:

db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
  return db.Order("orders.amount DESC")
}).Find(&users)

Nested Preloading

GORM supports nested preloading, for example:

db.Preload("Orders.OrderItems.Product").Preload("CreditCard").Find(&users)



db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users)

Embedded Preloading

Embedded Preloading is used for Embedded Struct, especially the
same struct. The syntax for Embedded Preloading is similar to Nested Preloading, they are divided by dot.

For example:

type Address struct {
  CountryID int
  Country   Country
}

type Org struct {
  PostalAddress   Address `gorm:"embedded;embeddedPrefix:postal_address_"`
  VisitingAddress Address `gorm:"embedded;embeddedPrefix:visiting_address_"`
  Address         struct {
    ID int
    Address
  } `gorm:"embedded;embeddedPrefix:nested_address_"`
}


db.Preload("Address.Country")  


db.Preload("PostalAddress.Country") 


db.Preload("NestedAddress.Address.Country") 


db.Preload(clause.Associations)

We can omit embedded part when there is no ambiguity.

type Address struct {
  CountryID int
  Country   Country
}

type Org struct {
  Address Address `gorm:"embedded"`
}

db.Preload("Address.Country")
db.Preload("Country") 

NOTE Embedded Preload only works with belongs to relation.
Values of other relations are the same in database, we can’t distinguish them.

GitHub tag (latest SemVer)

评论

登录后参与评论

正在加载评论…