Beego ORM 的 Read 方法仅支持按主键或单个显式字段名查询,不支持多字段联合查询;灵活单条查询应使用 QueryTable().Filter().One() 链式调用,注意 Filter 返回新 QuerySeter 实例、字段名大小写敏感、操作符需用双下划线语义化写法。

用 Read 查单条,但只认主键或显式字段名
Read 最常用也最容易出错:它默认只按结构体的主键(pk tag 标记的字段)查询,不会自动识别你填在其他字段里的值。
比如模型定义了 Id 是主键,那 user := User{LoginId: "admin"} 然后调 o.Read(&user) —— 这根本查不到,因为 ORM 忽略了 LoginId,只看 Id 是否有值。
- 正确写法是显式传字段名:
err = o.Read(&user, "LoginId") - 如果没匹配到数据,会返回
orm.ErrNoRows,不是nil错误,记得判断 - 注意:
Read不支持多字段联合查询(比如Read(&u, "LoginId", "Pwd")无效),它只接受一个字段名作为条件
用 QueryTable().Filter().One() 做灵活单条查询
要按非主键字段、或多个字段查唯一结果,必须走 QuerySeter 链式调用。这是实际项目里最稳的方式。
关键点在于:Filter 多次调用是 AND 关系,One 只取第一条并填充结构体。
- 表名可传字符串(如
"c_login")或模型指针(如&CLogin{}),推荐用字符串,避免反射开销和类型绑定问题 - 字段名要跟 struct tag 里的
column一致,比如orm:"column(LoginId)",就得写Filter("LoginId", loginId),不能写filter("login_id", ...) - 如果想查不到时不 panic,先用
Exist()判断:qs.Filter("LoginId", v).Exist()
Filter 的操作符决定 SQL 行为,别硬套 SQL 写法
Beego ORM 的 Filter 不是拼 SQL 字符串,而是通过双下划线 __ 后缀表达语义,比如 name__icontains 对应 LIKE '%xxx%'(大小写不敏感)。
-
Filter("age__gt", 18)→WHERE age > 18 -
Filter("name__in", "a", "b", "c")→WHERE name IN ('a','b','c') -
Filter("deleted", 0)是精确匹配;Filter("deleted__isnull", true)才是IS NULL - 字段名大小写敏感,
Filter("LoginId", ...)和Filter("loginid", ...)是两个不同字段(即使数据库列名小写)
别忽略 QueryTable 返回的是新 QuerySeter 实例
每次调 Filter、Exclude、Limit 都返回一个新的 QuerySeter,原对象不变。这看着像链式调用,其实是不可变设计。
- 错误写法:
qs := o.QueryTable("user"); qs.Filter("name", "x"); qs.One(&u)—— 中间Filter没接住返回值,实际没生效 - 正确写法:
o.QueryTable("user").Filter("name", "x").One(&u)或分步:qs := o.QueryTable("user"); qs = qs.Filter("name", "x"); qs.One(&u) - 这个特性容易被当成“方法链”直接用,但一旦中间漏了赋值或连写断开,条件就丢了,且无任何报错提示


















