Beego ORM 使用介绍,也可使用gorm作为Beego项目的数据库模块。
示例
package main
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
_ "github.com/go-sql-driver/mysql"
)
type City struct {
ID int `orm:"column(id);pk;auto"` // 第一个int类型的值会自动定义为主键,默认转为驼峰式 i_d
Name string
}
// TableName 指定数据库表名称
func (c *City) TableName() string {
return "city"
}
func main() {
// debug 模式
orm.Debug = true
// db
orm.RegisterDriver("mysql", orm.DRMySQL)
// 可以通过 aliasName 指定多个数据库
orm.RegisterDataBase("default", "mysql", "root:root@tcp(100.80.0.128:3306)/golangdev?charset=utf8")
orm.SetMaxIdleConns("default", 10)
orm.SetMaxOpenConns("default", 5)
//orm.RegisterModel(&City{})
orm.RegisterModel(new(City))
/* 注册orm 命令
$ go run main.go orm
orm command usage:
syncdb - auto create tables
sqlall - print sql of create tables
help - print this help
*/
//orm.RunCommand()
// 同步数据库
orm.RunSyncdb("default", false, true)
// 数据操作
// 插入
c := &City{
//ID: 1, // ID 自增,不需要指定
Name: "shanghai",
}
logs.Info(c)
ormer := orm.NewOrm()
//ormer := orm.NewOrmUsingDB("default")
ormer.Insert(c)
logs.Info(c) // 自动填充 id
cs := make([]*City, 5, 5)
for i := 0; i < 5; i++ {
cs[i] = &City{Name: fmt.Sprintf("c_%d", i)}
}
ormer.InsertMulti(2, cs)
// 查询
cr := &City{ID: 1}
err := ormer.Read(cr)
if err != nil {
logs.Info(err)
}
logs.Info(cr)
cr = &City{Name: "shanghai"}
err = ormer.Read(cr, "Name")
if err != nil {
logs.Info(err)
}
logs.Info(cr)
// 读,不存在创建
logs.Info(ormer.ReadOrCreate(cr, "Name"))
// 查询所有
//ormer.QueryTable("city")
queryset := ormer.QueryTable(&City{})
logs.Info(queryset)
logs.Info(queryset.Count())
var cs1 []*City
queryset.All(&cs1)
logs.Info(cs1)
/*
= exact iexact
> gt
< lt
>= gte
<= lte
in in
like contains startswith endswith icontains istartswith iendswith
*/
var cs2 []*City
queryset.Filter("name", "shanghai").All(&cs2)
logs.Info("cs2", cs2)
var cs3 []*City
queryset.Filter("id__gt", 5).All(&cs3)
logs.Info("cs3", cs3)
logs.Info(queryset.Filter("id__in", []int{1, 2, 3}).Count())
logs.Info(queryset.Filter("id__gt", 5).Filter("id__lt", 8).Count())
// 排查
logs.Info(queryset.Exclude("id__gt", 20).Count())
// 分页
var cs4 []*City
logs.Info(queryset.Filter("id__gt", 20).Limit(10).Offset(10).All(&cs4))
logs.Info("cs4", cs4)
//queryset.OrderBy("Name", "ID") // asc
//queryset.OrderBy("-Name") // desc
//queryset.One(&c)
// 复杂查询
//cond := orm.NewCondition()
//condor := cond.Or("id__gt", 20).Or("id__lt", 20)
//cond := cond.And("name__contains", "hai").AndCond(condor)
//queryset.SetCond(cond)
// 批量更新
//queryset.Update(orm.Params{"name": "shanghai"})
//queryset.Update(orm.Params{"name": "shanghai", "id": orm.ColValue(orm.ColAdd, 1)})
//// 更新
//cr.Name = "muodu"
//ormer.Update(cr)
//ormer.Update(cr, "Name")
//
//// 删除
//ormer.Delete(&City{ID: 2})
// 批量删除
//queryset.Filter("id__gt", 20).Delete()
// 原始 SQL
// 原始的db
//db, err := orm.GetDB("default")
//db.Ping()
//db.Exec()
//db.Query()
//db.QueryRow()
//rawseter := ormer.Raw("update/create/delete")
//rawseter.Exec()
//rawseter := ormer.Raw("select * from city")
//var c5 []*City
//rawseter.QueryRows(&c5)
//rawseter := ormer.Raw("select name, count(1) from city group by name")
//var result []orm.Params
//rawseter.Values(&result)
//logs.Info(result)
//
//var resultList []orm.ParamsList
//rawseter.ValuesList(&resultList)
//logs.Info(resultList)
// 事务
//ormer.Begin()
//...
}
常用命令:
# 同步表结构,仅对第一次创建、添加字段/索引生效,修改字段不会生效
go run main.go orm sqlall
表字段
type Post struct {
// 忽略 struct 中的字段
AnyField string `orm:"-"`
// 当 Field 类型为 int, int32, int64, uint, uint32, uint64 时,可以设置字段为自增健
ID int `orm:"auto;colume(id)"`
// 数据库表默认为 NOT NULL,设置 null 代表 ALLOW NULL
Name string `orm:"null"`
// 为单个字段增加索引
Name string `orm:"index"`
// 为单个字段增加 unique 键
Name string `orm:"unique"`
// 为字段设置 db 字段的名称
Name string `orm:"column(user_name)"`
// string 类型字段默认为 varchar(255),设置 size 以后,db type 将使用 varchar(size)
Title string `orm:"size(60)"`
// 默认值
Status int `orm:"default(1)"`
// 外键
User *User `orm:"rel(fk)"`
// 设置 float32, float64 类型的浮点精度
Money float64 `orm:"digits(12);decimals(4)"`
// 设置为 datetime 时,time.Time 字段的对应 db 类型使用 datetime
Created time.Time `orm:"auto_now_add;type(datetime)"`
// 设置为 date 时,time.Time 字段的对应 db 类型使用 date
// Created time.Time `orm:"auto_now_add;type(date)"`
Updated time.Time `orm:"auto_now;type(datetime)"`
// 为字段添加注释
Status int `orm:"default(1);description(这是状态字段)"`
// 为datetime字段设置精度值位数,不同DB支持最大精度值位数也不一致
Created time.Time `orm:"type(datetime);precision(4)"`
}
// 多字段索引
func (u *User) TableIndex() [][]string {
return [][]string{
[]string{"Id", "Name"},
}
}
// 多字段唯一键
func (u *User) TableUnique() [][]string {
return [][]string{
[]string{"Name", "Email"},
}
}
func (u *User) TableEngine() string {
return "innodb"
}
表关系
rel / reverse
type User struct {
...
Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
...
}
type Profile struct {
...
User *User `orm:"reverse(one)"`
...
}
说明:
- 查询管理数据,需要使用
orm.NewOrm().LoadRelated(user, "Profile")
外键
type Post struct {
...
User *User `orm:"rel(fk)"` // RelForeignKey relation
...
}
type User struct {
...
Posts []*Post `orm:"reverse(many)"` // fk 的反向关系
...
}
说明:
- 查询管理数据,需要使用
queryset.RelatedSel()
多对多
type Post struct {
...
Tags []*Tag `orm:"rel(m2m)"` // ManyToMany relation
...
}
type Tag struct {
...
Posts []*Post `orm:"reverse(many)"`
...
}
rel_table / rel_through
此设置针对 orm:"rel(m2m)"
的关系字段
- rel_table 设置自动生成的 m2m 关系表的名称,当设置 rel_table 时会忽略 rel_through
- rel_through 如果要在 m2m 关系中使用自定义的 m2m 关系表,通过这个设置其名称,格式为 pkg.path.ModelName,eg: app.models.PostTagRel,PostTagRel 表需要有到 Post 和 Tag 的关系
设置方法:
orm:"rel(m2m);rel_table(the_table_name)"
orm:"rel(m2m);rel_through(pkg.path.ModelName)"
on_delete
设置对应的 rel 关系删除时,如何处理关系字段。
- cascade 级联删除(默认值)
- set_null 设置为 NULL,需要设置 null = true
- set_default 设置为默认值,需要设置 default 值
- do_nothing 什么也不做,忽略
// 删除 Profile 时将设置 User.Profile 的数据库字段为 NULL
type User struct {
...
Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
...
}
type Profile struct {
...
User *User `orm:"reverse(one)"`
...
}
复杂查询
cond := orm.NewCondition()
cond = cond.Add("deleted_at__isnull", true)
qcond:=orm.NewCondition()
qcond = qcond.Or("key__icontains", q)
qcond = qcond.Or("host__name__icontains", q)
cond = cond.AddCond(qcond)
queryset.RelatedSel().SetCond(cond).All(&objects)