在使用 Go 的 GORM 进行三表关联查询时,你可以通过 Preload
方法来高效地获取关联数据。假设你有三个表:User
、Order
和 Product
,并且它们之间的关系如下:
User
有多个 Order
Order
属于一个 Product
你希望获取 User
的 UserName
字段以及与之关联的 Order
和 Product
数据。
首先,定义你的模型结构体:
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID uint
UserName string
Orders []Order
}
type Order struct {
ID uint
UserID uint
ProductID uint
Product Product
}
type Product struct {
ID uint
Name string
Price float64
}
接下来,建立与数据库的连接:
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 自动迁移模式
db.AutoMigrate(&User{}, &Order{}, &Product{})
}
使用 Preload
方法来预加载关联数据:
func main() {
// ... 数据库连接代码
var users []User
db.Preload("Orders").Preload("Orders.Product").Find(&users)
for _, user := range users {
fmt.Printf("User: %s\n", user.UserName)
for _, order := range user.Orders {
fmt.Printf(" Order ID: %d, Product: %s, Price: %.2f\n", order.ID, order.Product.Name, order.Product.Price)
}
}
}
Preload("Orders")
:预加载 User
的 Orders
关联数据。Preload("Orders.Product")
:预加载 Order
的 Product
关联数据。Find(&users)
:查询所有 User
数据,并自动填充关联的 Orders
和 Product
数据。如果你只想获取特定的字段,可以使用 Select
方法来指定字段:
db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
return db.Select("ID", "UserID", "ProductID")
}).Preload("Orders.Product", func(db *gorm.DB) *gorm.DB {
return db.Select("ID", "Name", "Price")
}).Select("ID", "UserName").Find(&users)
这样可以减少查询的字段数量,提高查询效率。
如果关联关系更复杂,比如 Product
还有其他的关联表,你可以继续嵌套使用 Preload
来加载更深层次的关联数据。
在实际应用中,记得处理可能的错误,例如数据库连接失败、查询失败等。
if err := db.Preload("Orders").Preload("Orders.Product").Find(&users).Error; err != nil {
log.Fatalf("Failed to query data: %v", err)
}
通过使用 GORM 的 Preload
方法,你可以高效地获取三表关联数据,并且可以通过 Select
方法来优化查询,减少不必要的字段加载。这种方法适用于大多数需要处理复杂关联查询的场景。