Preload
GORM allows eager loading relations in other SQL with Preload, for example:
1. type User struct {
2. gorm.Model
3. Username string
4. Orders []Order
5. }
7. type Order struct {
8. gorm.Model
9. UserID uint
10. Price float64
11. }
13. // Preload Orders when find users
14. db.Preload("Orders").Find(&users)
15. // SELECT * FROM users;
16. // SELECT * FROM orders WHERE user_id IN (1,2,3,4);
18. db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users)
19. // SELECT * FROM users;
20. // SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many
21. // SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one
22. // SELECT * FROM roles WHERE id IN (4,5,6); // belongs to
Joins Preloading
Preload loads the association data in a separate query, Join Preload will loads association data using inner join, for example:
1. db.Joins("Company").Joins("Manager").Joins("Account").First(&user, 1)
2. db.Joins("Company").Joins("Manager").Joins("Account").First(&user, "users.name = ?", "jinzhu")
3. db.Joins("Company").Joins("Manager").Joins("Account").Find(&users, "users.id IN ?", []int{1,2,3,4,5})
Join with conditions
1. db.Joins("Company", DB.Where(&Company{Alive: true})).Find(&users)
2. // SELECT `users`.`id`,`users`.`name`,`users`.`age`,`Company`.`id` AS `Company__id`,`Company`.`name` AS `Company__name` FROM `users` LEFT JOIN `companies` AS `Company` ON `users`.`company_id` = `Company`.`id` AND `Company`.`alive` = true;
NOTE
Join Preloadworks 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:
1. type User struct {
2. gorm.Model
3. Name string
4. CompanyID uint
5. Company Company
6. Role Role
7. Orders []Order
8. }
10. db.Preload(clause.Associations).Find(&users)
clause.Associations won’t preload nested associations, but you can use it with Nested Preloading together, e.g:
1. 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
1. // Preload Orders with conditions
2. db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
3. // SELECT * FROM users;
4. // SELECT * FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled');
6. db.Where("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
7. // SELECT * FROM users WHERE state = 'active';
8. // SELECT * FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled');
Custom Preloading SQL
You are able to custom preloading SQL by passing in func(db *gorm.DB) *gorm.DB, for example:
1. db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
2. return db.Order("orders.amount DESC")
3. }).Find(&users)
4. // SELECT * FROM users;
5. // SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC;
Nested Preloading
GORM supports nested preloading, for example:
1. db.Preload("Orders.OrderItems.Product").Preload("CreditCard").Find(&users)
3. // Customize Preload conditions for `Orders`
4. // And GORM won't preload unmatched order's OrderItems then
5. db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users)
