beego orm是一個(gè)基于Go進(jìn)行ORM操作的庫建丧,它采用了Go style方式對(duì)數(shù)據(jù)庫進(jìn)行操作排龄,實(shí)現(xiàn)了struct到數(shù)據(jù)表記錄的映射。
beego orm是一個(gè)十分輕量級(jí)的Go ORM框架翎朱,開發(fā)這個(gè)庫的本意降低復(fù)雜的ORM學(xué)習(xí)曲線橄维,盡可能在ORM的運(yùn)行效率和功能之間尋求一個(gè)平衡,beego orm是目前開源的Go ORM框架中實(shí)現(xiàn)比較完整的一個(gè)庫拴曲,而且運(yùn)行效率相當(dāng)不錯(cuò)争舞,功能也基本能滿足需求。
支持的數(shù)據(jù)庫驅(qū)動(dòng)
beego orm是支持database/sql標(biāo)準(zhǔn)接口的ORM庫澈灼,所以理論上來說竞川,只要數(shù)據(jù)庫驅(qū)動(dòng)支持database/sql接口就可以無縫的接入beego orm。目前測(cè)試過的驅(qū)動(dòng)包括下面幾個(gè):
Mysql:?github.com/go-mysql-driver/mysql
PostgreSQL:?github.com/lib/pq
SQLite:?github.com/mattn/go-sqlite3
Mysql:?github.com/ziutek/mymysql/godrv
安裝
beego orm支持go get方式安裝蕉汪,是完全按照Go Style的方式來實(shí)現(xiàn)的流译。
# go get github.com/astaxie/beego
初始化
首先你需要import相應(yīng)的數(shù)據(jù)庫驅(qū)動(dòng)包、database/sql標(biāo)準(zhǔn)接口包以及beego orm包者疤,如下所示:
import (
????"database/sql"
????"fmt"
????"github.com/astaxie/beego/orm"
????_ "github.com/go-sql-driver/mysql"
)
func init() {
????// 注冊(cè)驅(qū)動(dòng)
????orm.RegisterDriver("mysql", orm.DRMySQL)
????// 設(shè)置默認(rèn)數(shù)據(jù)庫
????orm.RegisterDataBase("default", "mysql", "root:1234@/test?charset=utf8", 30)
????// 注冊(cè)定義的model
????orm.RegisterModel(new(User))
????// 創(chuàng)建table
????orm.RunSyncdb("default", false, true)
}
PostgreSQL配置
// 導(dǎo)入驅(qū)動(dòng)
// _ "github.com/lib/pq"
// 注冊(cè)驅(qū)動(dòng)
orm.RegisterDriver("postgre", orm.DRPostgres)
// 設(shè)置默認(rèn)數(shù)據(jù)庫
orm.RegisterDataBase("default", "postgres", "user=root password=1234 dbname=test host=localhost port=5432 sslmode=disable")
MySQL配置
// 導(dǎo)入驅(qū)動(dòng)
// _ "github.com/go-sql-driver/mysql"
// 注冊(cè)驅(qū)動(dòng)
orm.RegisterDriver("mysql", orm.DRMySQL)
// 設(shè)置默認(rèn)數(shù)據(jù)庫
orm.RegisterDataBase("default", "mysql", "root:1234@/test?charset=utf8")
Sqlite配置
// 導(dǎo)入驅(qū)動(dòng)
// _ "github.com/mattn/go-sqlite3"
// 注冊(cè)驅(qū)動(dòng)
orm.RegisterDriver("sqlite", orm.DRSqlite)
// 設(shè)置默認(rèn)數(shù)據(jù)庫
orm.RegisterDataBase("default", "sqlite3", "./datas/test.db")
數(shù)據(jù)庫連接
導(dǎo)入必須的package之后福澡,我們需要打開到數(shù)據(jù)庫的鏈接,然后創(chuàng)建一個(gè)beego orm對(duì)象(以MySQL為例)驹马,如下所示:
func main() {
? ? o := orm.NewOrm()
}
示例代碼
package main
import (
????"fmt"
????"github.com/astaxie/beego/orm"
????_ "github.com/go-sql-driver/mysql"
)
// Model Struct
type User struct {
????Id? int
????Name string `orm:"size(100)"`
}
func init() {
????// 注冊(cè)驅(qū)動(dòng)
????orm.RegisterDriver("mysql", orm.DRMySQL)
????// 設(shè)置默認(rèn)數(shù)據(jù)庫
????orm.RegisterDataBase("default", "mysql", "root:1234@/test?charset=utf8", 30)
????// 注冊(cè)定義的model
????orm.RegisterModel(new(User))
????// 創(chuàng)建table
????orm.RunSyncdb("default", false, true)
}
func main() {
????o := orm.NewOrm()
????user := User{Name: "lai"}
????// 插入表
????id, err := o.Insert(&user)
????fmt.Printf("ID: %d, ERR:%v\n", id, err)
????// 更新表
????user.Name = "laiupdate"
????num, err := o.Update(&user)
????fmt.Printf("NUM:%d, ERR:%v\n", num, err)
????// 讀取ONE
????u := User{Id: user.Id}
????err = o.Read(&u)
????fmt.Printf("ERR:%v\n", err)
????// 刪除表
????num, err = o.Delete(&u)
????fmt.Printf("NUM:%d, ERR:%v\n", num, err)
}
數(shù)據(jù)庫表結(jié)構(gòu)對(duì)應(yīng)的struct
type Userinfo struct {
????Uid? ? int `PK` //如果表的主鍵不是id革砸,那么需要加上pk注釋除秀,顯式的說這個(gè)字段是主鍵
????Username? ? string
????Departname? string
????Created? ? time.Time
}
type User struct {
????Uid? ? ? ? ? int `PK` //如果表的主鍵不是id,那么需要加上pk注釋算利,顯式的說這個(gè)字段是主鍵
????Name? ? ? ? string
????Profile? ? *Profile? `orm:"rel(one)"` // OneToOne relation
????Post? ? ? ? []*Post `orm:"reverse(many)"` // 設(shè)置一對(duì)多的反向關(guān)系
}
type Profile struct {
????Id? ? ? ? ? int
????Age? ? ? ? int16
????User? ? ? ? *User? `orm:"reverse(one)"` // 設(shè)置一對(duì)一反向關(guān)系(可選)
}
type Post struct {
????Id? ? int
????Title string
????User? *User? `orm:"rel(fk)"`? ? //設(shè)置一對(duì)多關(guān)系
????Tags? []*Tag `orm:"rel(m2m)"`
}
type Tag struct {
????Id? ? int
????Name? string
????Posts []*Post `orm:"reverse(many)"`
}
func init() {
????// 需要在init中注冊(cè)定義的model
????orm.RegisterModel(new(Userinfo),new(User), new(Profile), new(Tag))
}
注意:beego orm針對(duì)駝峰命名會(huì)自動(dòng)幫你轉(zhuǎn)化成下劃線字段册踩,例如你定義了Struct名字為UserInfo,那么轉(zhuǎn)化成底層實(shí)現(xiàn)的時(shí)候是user_info效拭,字段命名也遵循該規(guī)則暂吉。
其他配置
SetMaxIdleConns
根據(jù)數(shù)據(jù)庫的別名,設(shè)置數(shù)據(jù)庫的最大空閑連接
orm.SetMaxIdleConns("default", 30)
SetMaxOpenConns
根據(jù)數(shù)據(jù)庫的別名缎患,設(shè)置數(shù)據(jù)庫的最大數(shù)據(jù)庫連接 (go >= 1.2)
orm.SetMaxOpenConns("default", 30)
Debug模式
目前beego orm支持打印調(diào)試慕的,你可以通過如下的代碼實(shí)現(xiàn)調(diào)試
orm.Debug = true
插入數(shù)據(jù)
下面的代碼演示了如何插入一條記錄,可以看到我們操作的是struct對(duì)象挤渔,而不是原生的sql語句肮街,最后通過調(diào)用Insert接口將數(shù)據(jù)保存到數(shù)據(jù)庫。
o := orm.NewOrm()
var user User
user.Name = "zxxx"
user.Departname = "zxxx"
id, err := o.Insert(&user)
if err == nil {
????fmt.Println(id)
}
我們看到插入之后user.Uid就是插入成功之后的自增ID判导。
同時(shí)插入多個(gè)對(duì)象:InsertMulti
類似sql語句
insert into table (name, age) values("slene", 28),("astaxie", 30),("unknown", 20)
第一個(gè)參數(shù) bulk 為并列插入的數(shù)量嫉父,第二個(gè)為對(duì)象的slice
返回值為成功插入的數(shù)量
users := []User{
? ? {Name: "slene"},
? ? {Name: "astaxie"},
? ? {Name: "unknown"},
? ? ...
}
successNums, err := o.InsertMulti(100, users)
bulk 為 1 時(shí),將會(huì)順序插入 slice 中的數(shù)據(jù)眼刃。
更新數(shù)據(jù)
繼續(xù)上面的例子來演示更新操作绕辖,現(xiàn)在user的主鍵已經(jīng)有值了,此時(shí)調(diào)用Insert接口鸟整,beego orm內(nèi)部會(huì)自動(dòng)調(diào)用update以進(jìn)行數(shù)據(jù)的更新而非插入操作引镊。
o := orm.NewOrm()
user := User{Uid: 1}
if o.Read(&user) == nil {
????user.Name = "MyName"
????if num, err := o.Update(&user); err == nil {
????????fmt.Println(num)
????}
}
Update 默認(rèn)更新所有的字段,可以更新指定的字段:
// 只更新 Name
o.Update(&user, "Name")
// 指定多個(gè)字段
// o.Update(&user, "Field1", "Field2", ...)
//Where:用來設(shè)置條件篮条,支持多個(gè)參數(shù)弟头,第一個(gè)參數(shù)如果為整數(shù),相當(dāng)于調(diào)用了Where("主鍵=?",值)涉茧。
查詢數(shù)據(jù)
beego orm的查詢接口比較靈活赴恨,具體使用請(qǐng)看下面的例子
例子1:根據(jù)主鍵獲取數(shù)據(jù)
o := orm.NewOrm()
var user User
user := User{Id: 1}
err = o.Read(&user)
if err == orm.ErrNoRows {
????fmt.Println("查詢不到")
} else if err == orm.ErrMissPK {
????fmt.Println("找不到主鍵")
} else {
????fmt.Println(user.Id, user.Name)
}
例子2:指定WHERE查詢條件
o := orm.NewOrm()
var user User
qs := o.QueryTable(user) // 返回 QuerySeter
qs.Filter("id", 1) // WHERE id = 1
qs.Filter("profile__age", 18) // WHERE profile.age = 18
例子3:WHERE IN查詢條件
qs.Filter("profile__age__in", 18, 20)
// WHERE profile.age IN (18, 20)
例子4:更加復(fù)雜的條件
qs.Filter("profile__age__in", 18, 20).Exclude("profile__lt", 1000)
// WHERE profile.age IN (18, 20) AND NOT profile_id < 1000
可以通過如下接口獲取多條數(shù)據(jù),請(qǐng)看示例
例子1伴栓,根據(jù)條件age>17伦连,獲取20位置開始的10條數(shù)據(jù)的數(shù)據(jù)
var allusers []User
qs.Filter("profile__age__gt", 17)
// WHERE profile.age > 17
例子2,limit默認(rèn)從10開始钳垮,獲取10條數(shù)據(jù)
qs.Limit(10, 20)
// LIMIT 10 OFFSET 20 注意跟SQL反過來的
刪除數(shù)據(jù)
beedb提供了豐富的刪除數(shù)據(jù)接口惑淳,請(qǐng)看下面的例子
例子1,刪除單條數(shù)據(jù)
o := orm.NewOrm()
if num, err := o.Delete(&User{Id: 1}); err == nil {
fmt.Println(num)
}
Delete 操作會(huì)對(duì)反向關(guān)系進(jìn)行操作饺窿,此例中 Post 擁有一個(gè)到 User 的外鍵歧焦。刪除 User 的時(shí)候,如果 on_delete 設(shè)置為默認(rèn)的級(jí)聯(lián)操作肚医,將刪除對(duì)應(yīng)的 Post绢馍。
關(guān)聯(lián)查詢
基于struct的關(guān)聯(lián)查詢:
type Post struct {
Id? ? int? ? `orm:"auto"`
Title string `orm:"size(100)"`
User? *User? `orm:"rel(fk)"`
}
var posts []*Post
qs := o.QueryTable("post")
num, err := qs.Filter("User__Name", "slene").All(&posts)
Group By 和 Having
GroupBy:用來指定進(jìn)行g(shù)roupby的字段
Having:用來指定having執(zhí)行的時(shí)候的條件
OrderBy
qs.OrderBy("id", "-profile__age")
// ORDER BY id ASC, profile.age DESC
qs.OrderBy("-profile__age", "profile")
// ORDER BY profile.age DESC, profile_id ASC
使用原生SQL
1向瓷、簡單示例:
o := orm.NewOrm()
var r orm.RawSeter
r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
2、復(fù)雜原生SQL:
func (m *User) Query(name string) user []User {
????var o orm.Ormer
????var rs orm.RawSeter
????o = orm.NewOrm()
????rs = o.Raw("SELECT * FROM user "+
????????????????"WHERE name=? AND uid>10 "+
????????????????"ORDER BY uid DESC "+
????????????????"LIMIT 100", name)
????//var user []User
????num, err := rs.QueryRows(&user)
????if err != nil {
????????fmt.Println(err)
????} else {
????????fmt.Println(num)
????????//return user
????}
????return
}
更多說明舰涌,請(qǐng)到:beego.me