GORM执行多表Join关联查询时返回值对应的结构体类型问题
GORM联表Join查询的结果接收方案
我们先明确提前定义的两个GORM模型结构体:
type A struct { ID string `gorm:"primary_key"` Name string } type B struct { ID string `gorm:"primary_key"` AId string A A `gorm:"foreignkey:AId"` Val string }
单表查询时直接传对应A或B类型的切片指针给GORM接收结果即可,但执行以下Join查询时,不能直接套用单表的结构体:
select * from a join b on a.id = b.a_id;
核心原因是A、B两张表都存在名为id的主键字段,直接用原有单表结构接收会出现同名字段映射覆盖的问题,正确的接收方式有两种:
- 自定义专用联表结果结构体(最推荐,兼容性最好)
针对联表返回的字段单独定义结构体,写SQL时给重名字段起好别名,通过gorm的column标签做字段映射,完全避免映射错乱问题:// 结构体字段和联表返回的列一一对应 type ABResult struct { AID string `gorm:"column:aid"` // 对应A表的ID Name string // 对应A表的Name BID string `gorm:"column:bid"` // 对应B表的ID AId string // 对应B表的AId Val string // 对应B表的Val } // 调用示例 var res []ABResult // SQL里给重名的id起别名,和结构体标签对应 db.Raw(` select a.id as aid, a.name, b.id as bid, b.a_id, b.val from a join b on a.id = b.a_id `).Scan(&res) - 嵌套原有模型结构体接收
如果不想重复写字段定义,可以直接嵌套A、B两个模型,写SQL时用[结构体名]__[字段名]的格式给重名字段起别名,GORM会自动完成嵌套字段的映射:type ABResult struct { A B } var res []ABResult db.Raw(` select a.id as "a__id", a.name, b.id as "b__id", b.a_id, b.val from a join b on a.id = b.a_id `).Scan(&res)
避坑提醒:不要直接用预定义的B结构体接收原生Join查询的结果,B结构体虽然嵌套了A字段,但
select *返回的两个id列会出现映射冲突,最终拿到的ID字段值会出现覆盖错误。
内容的提问来源于stack exchange,提问作者zli
相关产品推荐
相关产品推荐

