You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 13:36:18