需求背景
我有两个 MySQL 数据表:
- 员工表 staff
- 薪资表 salary。这里有员工 ID 字段作为外键关联员工表。
我定义的薪资 Struct 结构体,包含了 embedded 字段 Staff,用于关联员工信息:
type Salary struct {
gorm.Model
StaffId uint
Staff Staff `gorm:"foreignKey:StaffId"`
Amount float64
}
我需要在返回薪资信息列表时,同时返回员工的详细信息(通过 Preload 预加载实现),并且根据员工的某些字段进行过滤(通过 Left Join 实现)。
golang 代码
下面是一个示例代码,展示了如何使用 Gorm 的 Preload 和 Left Join 来实现这个需求:
func GetSalaryList(c *gin.Context) {
var items []Salary
db := models.DB.Model(&Salary{}).
Select("salary.*").
Joins("LEFT JOIN staff ON salary.staff_id = staff.id") // 使用 Left Join 关联员工表
// 根据员工姓名进行过滤
if name, isExist := c.GetQuery("name"); isExist {
db = db.Where("staff.name LIKE ?", fmt.Sprintf("%%%s%%", name))
}
// After a Chain method, Finisher Method, GORM returns an initialized
// *gorm.DB instance, which is NOT safe to reuse anymore, or new generated
// SQL might be polluted by the previous conditions.
// In order to reuse a initialized *gorm.DB instance, you can use a
// New Session Method to create a shareable *gorm.DB
db = db.Session(&gorm.Session{})
var count int64 = 0
db.Distinct("salary.id").Count(&count)
db.Preload("Staff"). // 预加载 Staff 关联
Order("salary.id desc").
Limit(limit).
Offset((page - 1) * limit).
Find(&items)
}
需要注意的两个地方:
- Preload 需要在 count 统计之后使用,因为 count 统计时不需要预加载数据。也可能会出现 count 返回 0 的问题。
- count 加上 Distinct("salary.id"),避免因为 Left Join 导致的重复记录计数问题。
我发现 VSCode 里的 Github Copilot 的 GPT-5 mini 模型,在有项目代码上下文的情况下,比 DeepSeek 强太多了。 不用去解释过多的前提。所以网页版的 AI 工具,效率还是差一些。
关于作者 🌱
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式