★ ORM 设计哲学:g.DB 与链式操作、Scan/All 区别
结论:GoFrame ORM(gdb)以“链式操作 + 约定映射”为核心:g.DB() 是单例数据库入口,Model().Where()...Scan() 一气呵成;All 返回原始结果集,Scan 按目标结构体自动映射;配合 dao 代码生成与软删除等约定,日常 CRUD 几乎不写手拼 SQL。
一、核心概念
- g.DB():默认分组单例(g.DB("order") 取其他分组),配置在 database 节点。
- 链式起点:g.Model("user") 或生成的 dao.User.Ctx(ctx)。
- 常用链式:Where/WherePri/Fields/Order/Group/Having/Limit/Page/Scan 等。
- 取数方法:All()→gdb.Result(原始记录集);One()→单条 gdb.Record;Scan(&obj) 自动映射到结构体/切片/基本类型。
- 字段安全:条件参数用 ? 占位或 map/struct 传参,杜绝字符串拼接注入。
二、Scan 与 All 对比
| 方法 | 返回 | 适用 |
|---|---|---|
| All() | gdb.Result,需再手动转换 | 只要原始数据/二次加工 |
| One() | gdb.Record 单条 | 取单行原始数据 |
| Scan(&users) | 自动映射任意目标 | 直接进业务结构体,最常用 |
代码示例
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
Age int `json:"age"`
}
// 列表:Scan 到结构体切片
var users []User
err := g.Model("user").Ctx(ctx).
Where("age > ?", 18).
OrderAsc("id").
Limit(10).
Scan(&users)
// 单条:按主键取
var u User
err := dao.User.Ctx(ctx).WherePri(1).Scan(&u)
// 约定:存在 deleted_at 字段则自动软删除
_, _ = dao.User.Ctx(ctx).WherePri(1).Delete() // UPDATE deleted_at=now
_ = dao.User.Ctx(ctx).Unscoped().WherePri(1).Scan(&u) // Unscoped 忽略软删除
常见追问 / 记忆点
- 追问:created_at/updated_at 谁维护?→ 表存在这些字段时 gdb 自动写入维护,属“约定优于配置”(以官方文档为准)。
- 追问:与 GORM 的链式有何差异?→ 风格类似,但 gdb 与 gf 的 dao 生成、日志、错误码、软删除约定深度打通。
- 记忆点:All 拿原始、Scan 进结构体、Unscoped 开软删、Ctx 永远首参。