relatedsel()必须链式调用one()/all()才生效,仅调用不触发join;默认只加载一级外键关联,多级需显式指定路径;外键字段名须与orm:"rel(fk)"标签中的column一致,否则静默失败。

beego ORM 的 RelatedSel() 必须配合 QueryTable() 使用
单独调用 RelatedSel() 不会触发 JOIN,它只是给后续的 All() 或 One() 做准备。常见错误是写了 o.QueryTable("user").RelatedSel().Filter("id", 1) 却没接 .One() 或 .All(),结果关联字段还是 nil。
正确写法必须链式到底:
var user User
err := o.QueryTable("user").Filter("id", 1).RelatedSel().One(&user)
// 或
var users []User
_, err := o.QueryTable("user").Filter("name__contains", "a").RelatedSel().All(&users)
-
RelatedSel()默认只加载一级外键关联(比如User.Profile),不会递归加载Profile.Address - 若要加载二级关联,得显式指定路径:
RelatedSel("Profile", "Profile__Address") - 不支持对多对多中间表字段做条件过滤(如
Tags__name__contains),会报错或忽略
外键字段名必须与 struct tag 中的 rel(fk) 一致
Beego ORM 不靠字段名推断外键,而是依赖 orm:"rel(fk)" 标签。如果结构体里写的是 Arctype *Arctype,但数据库字段叫 type_id,就必须在 tag 里声明对应关系:
type Archives struct {
Id int
Title string
Arctype *Arctype `orm:"rel(fk);column(arctype_id)"`
}
- 漏掉
column(xxx)会导致 ORM 尝试用默认名(如arctype_id)查,而实际字段是typeid,查询时静默失败或返回空 - 一对多反向关系(
reverse(many))不要手动设外键字段,ORM 自动处理 - 多对多关系必须用
rel(m2m)+ 中间表注册,不能仅靠两个外键字段模拟
Raw() 查询中 JOIN 的字段别名必须和 Values() 接收的 map key 对应
用 Raw() 手写 JOIN 时,Values(&maps) 依赖 SQL 中的列别名。如果 SELECT 写成 arc.title, art.typename,那 maps[0]["title"] 和 maps[0]["typename"] 才有值;写成 arc.title as t, art.typename as n,就得用 "t" 和 "n"。
- 别名含点号(如
art.typename)会被转成"art.typename"字符串,但某些版本解析不稳定,建议统一用下划线分隔(art_typename) -
ValuesMap()可以避免 key 冲突,但要求每行结果 key 唯一,JOIN 后同名列(如两个表都有id)必须显式别名 -
Raw().Exec()不支持参数化 JOIN 条件,WHERE部分的 ? 占位符只能用于最后的过滤条件
事务中混合使用 RelatedSel() 和 Raw() 容易丢连接上下文
在一个 orm.Begin() 事务里,RelatedSel() 用的是事务绑定的 Orm 实例,但 Raw() 如果是新 orm.NewOrm() 创建的,就脱离了事务——数据看似写入,实际 rollback 后消失。
- 务必复用同一个
Orm实例:o := orm.NewOrm(); tx, _ := o.Begin(); tx.Raw(...).Exec() -
RelatedSel()在事务中能正常加载关联,但Raw()返回的 struct 不会自动填充关联字段,得自己 join 或二次查询 - 高并发下
SetMaxOpenConns设太小会导致RelatedSel()抢不到连接,超时前先查主表再查关联表反而更稳
orm.Debug = true 看生成的 SQL,比对着文档猜快得多。











