Beego ORM增删改查必须先完成三步初始化:注册驱动、注册数据库、注册模型并调用RunSyncdb,否则操作会panic或静默失败;所有CRUD均严格依赖已注册模型的结构体实例及主键字段。

Beego ORM 的增删改查必须先完成初始化
没注册数据库、没注册模型、没调用 RunSyncdb,后面所有操作都会 panic 或静默失败。常见现象是 o.Read(&user) 返回 no rows in result set,但其实根本没连上表——因为表压根没建。
关键三步缺一不可:
-
orm.RegisterDriver("mysql", orm.DRMySQL)(驱动注册) -
orm.RegisterDataBase("default", "mysql", "root:pass@tcp(127.0.0.1:3306)/test?charset=utf8")(DB 连接字符串要带charset=utf8,否则中文乱码) -
orm.RegisterModel(new(User))+orm.RunSyncdb("default", false, true)(false表示不自动建表,true表示结构变更时自动 alter)
Insert 和 Read 的主键逻辑容易搞反
o.Insert(&user) 会把自增 ID 写回 user.Id,但 o.Read(&user) 默认只认 user.Id 字段做主键查询,且不校验其他字段是否为空。如果你传的是 user.Name = "zq" 却没传 user.Id,直接调 o.Read(&user) 就会报错 id is empty。
正确做法:
- 主键查询:只设
user.Id = 1,然后o.Read(&user) - 非主键查询:设好条件字段,比如
user.Name = "zq",再调o.Read(&user, "Name"),第二个参数必须显式传字段名 - 批量插入慎用
InsertMulti:它不返回每条记录的 ID,只返回总行数;如果中间某条失败,整个事务回滚(默认无事务包装)
Update 必须先 Read 再改再 Update
o.Update(&user) 不会根据字段值生成 WHERE 条件,它只按主键更新整行。如果你只写了 user.Name = "new" 却没设 user.Id,就会更新整张表所有行(MySQL 默认允许,但数据全毁)。
安全写法只有两种:
- 先
o.Read(&user, "Id")查出原数据,再改字段,最后o.Update(&user) - 用
QuerySeter显式控制条件:o.QueryTable("user").Filter("name", "old").Update(orm.Params{"name": "new"})
注意:Update 返回的是受影响行数,不是成功与否的布尔值;错误时 err 才非 nil。
Delete 操作没有“软删除”默认行为
o.Delete(&user) 是硬删,且同样依赖 user.Id。如果只传 user.Name = "xxx" 就调 Delete,会删掉主键为 0 的那条(通常不存在),看似成功实则没删任何数据。
更危险的是误删:
- 想删 name 是 "xxx" 的所有用户?必须用
QuerySeter:o.QueryTable("user").Filter("name", "xxx").Delete() - 原生 SQL 删除更可控:
o.Raw("DELETE FROM user WHERE name = ?", "xxx").Exec(),返回RowsAffected()可验证删了几行 - 别依赖
RunSyncdb的 auto-drop:它只管表结构,不管数据


















