插件窝 干货文章 Golang Gorm框架:如何高效实现三表关联查询并获取User.UserName?

Golang Gorm框架:如何高效实现三表关联查询并获取User.UserName?

查询 User Preload Orders 438    来源:    2025-03-15

在使用Golang的Gorm框架进行三表关联查询时,可以通过PreloadJoins等方法来实现高效的查询。假设你有三个表:UserOrderProduct,并且它们之间的关系如下:

  • User 表有一个或多个 Order
  • Order 表有一个或多个 Product

你想要查询某个用户的用户名(User.UserName),并且同时获取该用户的所有订单以及订单中的产品信息。

1. 定义模型

首先,定义你的模型结构体:

type User struct {
    ID       uint
    UserName string
    Orders   []Order
}

type Order struct {
    ID       uint
    UserID   uint
    Products []Product
}

type Product struct {
    ID      uint
    OrderID uint
    Name    string
}

2. 使用 Preload 进行关联查询

Preload 是Gorm中用于预加载关联数据的方法。你可以通过链式调用 Preload 来加载嵌套的关联数据。

var user User
db.Preload("Orders.Products").First(&user, 1) // 假设你要查询ID为1的用户
fmt.Println(user.UserName)

在这个例子中,Preload("Orders.Products") 会加载用户的所有订单以及每个订单中的产品。

3. 使用 Joins 进行关联查询

如果你只需要查询特定的字段(例如 User.UserName),并且不需要加载整个关联对象,可以使用 Joins 来进行更高效的查询。

var userName string
db.Table("users").
    Select("users.user_name").
    Joins("JOIN orders ON orders.user_id = users.id").
    Joins("JOIN products ON products.order_id = orders.id").
    Where("users.id = ?", 1).
    Scan(&userName)

fmt.Println(userName)

在这个例子中,我们使用 Joins 来连接 usersordersproducts 表,并且只查询 users.user_name 字段。

4. 结合 PreloadSelect 进行优化

如果你需要加载部分关联数据,并且只选择特定的字段,可以结合 PreloadSelect 来进行优化。

var user User
db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
    return db.Select("id, user_id") // 只选择需要的字段
}).
Preload("Orders.Products", func(db *gorm.DB) *gorm.DB {
    return db.Select("id, order_id, name") // 只选择需要的字段
}).
First(&user, 1)

fmt.Println(user.UserName)

在这个例子中,我们使用 Preload 加载 OrdersOrders.Products,但只选择需要的字段,以减少查询的数据量。

5. 使用 Raw 进行复杂查询

对于非常复杂的查询,你可以直接使用 Raw 方法来编写原生SQL查询。

var userName string
db.Raw(`
    SELECT users.user_name
    FROM users
    JOIN orders ON orders.user_id = users.id
    JOIN products ON products.order_id = orders.id
    WHERE users.id = ?
`, 1).Scan(&userName)

fmt.Println(userName)

总结

  • Preload:适用于需要加载整个关联对象的场景。
  • Joins:适用于只需要查询特定字段的场景。
  • Select:可以结合 PreloadJoins 来优化查询,减少不必要的数据加载。
  • Raw:适用于非常复杂的查询场景。

根据你的具体需求选择合适的方法来实现高效的三表关联查询。