GORM如何仅单次JOIN关联表实现预加载及跨关联表条件过滤
问题解决步骤
1. 先修正结构体的GORM关联标签
你当前的关联标签foreignKey和references配置颠倒了,需要调整为:
type SonModel struct { ID int64 Age int Name string FatherID int64 Father FaterModel `gorm:"foreignKey:FatherID;references:ID"` // 修正:外键是当前结构体的FatherID,关联父表的ID } type FaterModel struct { ID int64 Name string GrandID int64 Grand GrandModel `gorm:"foreignKey:GrandID;references:ID"` // 同理修正 } type GrandModel struct { ID int64 Name string }
2. 删除重复的自定义JOIN语句
GORM的Joins("关联名")方法会自动根据你定义的关联规则生成JOIN语句,不需要额外手动编写JOIN语句。同时如果要关联深层的Grand表,直接使用嵌套关联语法Joins("Father.Grand")即可,搭配Preload预加载关联数据不会重复生成JOIN。
3. 调整查询代码适配需求
// 模糊查询参数预处理 likeStr := "%" + name + "%" // 构建查询 db = db.Joins("Father").Joins("Father.Grand").Preload("Father.Grand") db = db.Where("son.age = ?", 15) db = db.Where("father.name LIKE ? OR son.name LIKE ? OR grand.name LIKE ?", likeStr, likeStr, likeStr) // 自定义select实现to_json输出 db = db.Select("son.id, son.name, to_json(father.*) as father") // 执行查询 var sons []SonModel err := db.Find(&sons).Error
额外说明
- 如果你不需要Grand表的字段做过滤,可以去掉
Joins("Father.Grand"),只保留Preload("Father.Grand")即可,此时GORM会用单独的查询预加载Grand数据,不会产生JOIN语句,性能更高。 - 所有关联表的字段在Where中直接用
表名.字段名的方式调用即可,GORM生成的关联JOIN的表别名和结构体对应的表名默认一致,不需要额外处理。 - 如果需要和你提供的原生SQL一致使用INNER JOIN而非默认的LEFT JOIN,可以替换
Joins("Father")为Joins("INNER JOIN father ON father.id = son.father_id")即可。
内容的提问来源于stack exchange,提问作者Todd
相关产品推荐
相关产品推荐

