Beego ORM 多表关联查询核心是模型字段声明 orm:"rel(fk)" + RelatedSel() 触发自动 JOIN 加载;不声明外键、不注册模型、不调用 RelatedSel(),则无法获取关联数据。

Beego ORM 做多表关联查询,核心不是写 JOIN,而是靠模型字段声明 + RelatedSel() 触发自动关联加载;不声明外键关系、不注册模型、不调用 RelatedSel(),就查不到关联数据。
必须在模型里用 orm:"rel(fk)" 显式声明外键关系
Beego 不会根据字段名(如 user_id)自动推断关联,必须在结构体字段上加 tag。常见错误是只定义了普通 int 字段,没加 rel 标签:
-
UserID int→ 不触发关联,RelatedSel()无效 -
User *User `orm:"rel(fk)"`→ 正确,ORM 才知道该查user表并做 left join
外键字段默认按结构体名小写生成(如 User → user_id),若数据库字段名不同,需额外指定:User *User `orm:"rel(fk);column(user_fk_id)"`。
RelatedSel() 是关联查询的开关,不是可选优化
调用 QueryTable().RelatedSel() 才会真正生成 JOIN SQL;漏掉这步,哪怕模型声明正确,也只查主表:
var articles []models.Article
o.QueryTable("article").Filter("id__gt", 10).All(&articles) // 只查 article 表,Arctype 字段为空
o.QueryTable("article").Filter("id__gt", 10).RelatedSel().All(&articles) // 查 article + left join arctype
支持限定关联表字段:RelatedSel("arctype"),但不能控制 JOIN 类型(固定为 LEFT JOIN);如需 INNER JOIN 或自定义 ON 条件,必须用 Raw()。
一对多、多对多要配 reverse 关系,否则反向查失败
比如 Author 有一组 Article,想从作者查文章,得在 Author 模型里声明:
Articles []*Article `orm:"reverse(many)"`
然后这样查:
var author models.Author
o.QueryTable("author").Filter("id", 1).RelatedSel("articles").One(&author)
// author.Articles 就是查到的文章切片
注意:reverse(many) 字段类型必须是切片,且目标模型必须已注册(RegisterModel());否则运行时 panic 或返回空 slice,无明确报错。
关联字段访问前务必检查非空,容易 panic
因为 RelatedSel() 是 LEFT JOIN,关联记录可能不存在。直接访问 article.Arctype.Typename 会 panic if Arctype == nil:
- 安全写法:
if article.Arctype != nil { fmt.Println(article.Arctype.Typename) } - 别依赖
IsNil或== nil判断——Go 结构体指针未初始化就是nil,但 ORM 不保证所有字段都赋值
复杂关联链(如 A → B → C)建议拆成两步查,避免嵌套空指针和 SQL 性能陡降;RelatedSel() 最多支持两级(A.RelatedSel().RelatedSel("b")),再深就失效。











