Beego Models 之 一

來源:互聯網
上載者:User

模型(Models)- beego ORM

原文

beego ORM 是一個強大的 Go 語言 ORM 架構。她的靈感主要來自 Django ORM 和 SQLAlchemy。

目前該架構仍處於開發階段,可能發生任何導致不相容的改動。

已支援資料庫驅動:

  • MySQL:github.com/go-sql-driver/mysql
  • PostgreSQL:github.com/lib/pq
  • Sqlite3:github.com/mattn/go-sqlite3

以上資料庫驅動均通過基本測試,但我們仍需要您的反饋。

ORM 特性:

  • 支援 Go 的所有類型儲存
  • 輕鬆上手,採用簡單的 CRUD 風格
  • 自動 Join 關聯表
  • 跨資料庫相容查詢
  • 允許直接使用 SQL 查詢/映射
  • 嚴格完整的測試保證 ORM 的穩定與健壯

安裝 ORM:

go get github.com/astaxie/beego/orm

ORM 使用方法

比較規範的,現在models的檔案夾下建立model的對象,所有的關於資料庫的操作都是在models中進行的,controller調用models中的方法即可。

models.go:
package mainimport (    "github.com/astaxie/beego/orm" //匯入包)//定義 struct和資料表進行映射的type User struct {    Id          int    Name        string    Profile     *Profile   `orm:"rel(one)"` // OneToOne relation    Post        []*Post `orm:"reverse(many)"` // 設定一對多的反向關係}type Profile struct {    Id          int    Age         int16    User        *User   `orm:"reverse(one)"` // 設定一對一反向關係(可選)}type Post struct {    Id    int    Title string    User  *User  `orm:"rel(fk)"`    //設定一對多關聯性    Tags  []*Tag `orm:"rel(m2m)"`}type Tag struct {    Id    int    Name  string    Posts []*Post `orm:"reverse(many)"`}func init() {    // 需要在init中註冊定義的model    orm.RegisterModel(new(User), new(Post), new(Profile), new(Tag))}
main.go
package mainimport (    "fmt"    "github.com/astaxie/beego/orm"    _ "github.com/go-sql-driver/mysql" // 只是調用init方法)func init() {    orm.RegisterDriver("mysql", orm.DRMySQL)    orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8")}func main() {    o := orm.NewOrm()    o.Using("default") // 預設使用 default,你可以指定為其他資料庫    profile := new(Profile)    profile.Age = 30    user := new(User)    user.Profile = profile    user.Name = "slene"    fmt.Println(o.Insert(profile))    fmt.Println(o.Insert(user))}

資料庫的設定

目前 ORM 支援三種資料庫,以下為測試過的 driver

將你需要使用的 driver 加入 import 中

import (    _ "github.com/go-sql-driver/mysql"    _ "github.com/lib/pq"    _ "github.com/mattn/go-sqlite3")

RegisterDriver

三種預設資料庫類型

// For version 1.6orm.DRMySQLorm.DRSqliteorm.DRPostgres// < 1.6orm.DR_MySQLorm.DR_Sqliteorm.DR_Postgres
// 參數1   driverName// 參數2   資料庫類型// 這個用來設定 driverName 對應的資料庫類型// mysql / sqlite3 / postgres 這三種是預設已經註冊過的,所以可以無需設定orm.RegisterDriver("mysql", orm.DRMySQL)

RegisterDataBase

ORM 必須註冊一個別名為 default 的資料庫,作為預設使用。

ORM 使用 golang 自己的串連池

// RegisterDataBase Setting the database connect params. Use the database driver self dataSource args.func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) error {    var (        err error        db  *sql.DB        al  *alias    )    db, err = sql.Open(driverName, dataSource)    if err != nil {        err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())        goto end    }    al, err = addAliasWthDB(aliasName, driverName, db)    if err != nil {        goto end    }    al.DataSource = dataSource    detectTZ(al)    for i, v := range params {        switch i {        case 0:            SetMaxIdleConns(al.Name, v)        case 1:            SetMaxOpenConns(al.Name, v)        }    }end:    if err != nil {        if db != nil {            db.Close()        }        DebugLog.Println(err.Error())    }    return err}
// 參數1        資料庫的別名,用來在 ORM 中切換資料庫使用// 參數2        driverName// 參數3        對應的連結字串orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8")// 參數4(可選)  設定最大空閑串連// 參數5(可選)  設定最大資料庫連接 (go >= 1.2)maxIdle := 30maxConn := 30orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", maxIdle, maxConn)

SetMaxIdleConns

根據資料庫的別名,設定資料庫的最大空閑串連

orm.SetMaxIdleConns("default", 30)

SetMaxOpenConns

根據資料庫的別名,設定資料庫的最大資料庫連接 (go >= 1.2)

orm.SetMaxOpenConns("default", 30)

時區設定

ORM 預設使用 time.Local 本地時區

  • 作用於 ORM 自動建立的時間
  • 從資料庫中取回的時間轉換成 ORM 本地時間

如果需要的話,你也可以變更

// 設定為 UTC 時間orm.DefaultTimeLoc = time.UTC

ORM 在進行 RegisterDataBase 的同時,會擷取資料庫使用的時區,然後在 time.Time 類型存取時做相應轉換,以匹配時間系統,從而保證時間不會出錯。

注意:

  • 鑒於 Sqlite3 的設計,存取預設都為 UTC 時間
  • 使用 go-sql-driver 驅動時,請注意參數設定
    從某一版本開始,驅動預設使用 UTC 時間,而非本地時間,所以請指定時區參數或者全部以 UTC 時間存取
    例如:root:root@/orm_test?charset=utf8&loc=Asia%2FShanghai
    參見 loc / parseTime

註冊模型

如果使用 orm.QuerySeter 進行進階查詢的話,這個是必須的。

反之,如果只使用 Raw 查詢和 map struct,是無需這一步的。您可以去查看 Raw SQL 查詢

RegisterModel

將你定義的 Model 進行註冊,最佳設計是有單獨的 models.go 檔案,在他的 init 函數中進行註冊。

迷你版 models.go

package mainimport "github.com/astaxie/beego/orm"type User struct {    Id   int    Name string}func init(){    orm.RegisterModel(new(User))}

RegisterModel 也可以同時註冊多個 model

orm.RegisterModel(new(User), new(Profile), new(Post))

詳細的 struct 定義請查看文檔 模型定義

RegisterModelWithPrefix

使用表名首碼

orm.RegisterModelWithPrefix("prefix_", new(User))

建立後的表名為 prefix_user

NewOrmWithDB

有時候需要自行管理串連池與資料庫連結(比如:go 的連結池無法讓兩次查詢使用同一個連結的)

但又想使用 ORM 的查詢功能

var driverName, aliasName string// driverName 是驅動的名稱// aliasName 是當前 db 的自訂別名var db *sql.DB...o := orm.NewOrmWithDB(driverName, aliasName, db)

GetDB

從登入的資料庫返回 *sql.DB 對象,預設返回別名為 default 的資料庫。

db, err := orm.GetDB()if err != nil {    fmt.Println("get default DataBase")}db, err := orm.GetDB("alias")if err != nil {    fmt.Println("get alias DataBase")}

ResetModelCache

重設已經註冊的模型 struct,一般用於編寫測試案例

orm.ResetModelCache()

ORM 介面使用

使用 ORM 必然接觸的 Ormer 介面,我們來熟悉一下

var o Ormero = orm.NewOrm() // 建立一個 Ormer// NewOrm 的同時會執行 orm.BootStrap (整個 app 只執行一次),用以驗證模型之間的定義並緩衝。

切換資料庫,或者,進行交易處理,都會作用於這個 Ormer 對象,以及其進行的任何查詢。

所以:需要 切換資料庫交易處理 的話,不要使用全域儲存的 Ormer 對象。

// Ormer define the orm interfacetype Ormer interface {    // read data to model    // for example:    //  this will find User by Id field    //  u = &User{Id: user.Id}    //  err = Ormer.Read(u)    //  this will find User by UserName field    //  u = &User{UserName: "astaxie", Password: "pass"}    //  err = Ormer.Read(u, "UserName")    Read(md interface{}, cols ...string) error    // Like Read(), but with "FOR UPDATE" clause, useful in transaction.    // Some databases are not support this feature.    ReadForUpdate(md interface{}, cols ...string) error    // Try to read a row from the database, or insert one if it doesn't exist    ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error)    // insert model data to database    // for example:    //  user := new(User)    //  id, err = Ormer.Insert(user)    //  user must a pointer and Insert will set user's pk field    Insert(interface{}) (int64, error)    // mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value")    // if colu type is integer : can use(+-*/), string : convert(colu,"value")    // postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value")    // if colu type is integer : can use(+-*/), string : colu || "value"    InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)    // insert some models to database    InsertMulti(bulk int, mds interface{}) (int64, error)    // update model to database.    // cols set the columns those want to update.    // find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns    // for example:    // user := User{Id: 2}    //  user.Langs = append(user.Langs, "zh-CN", "en-US")    //  user.Extra.Name = "beego"    //  user.Extra.Data = "orm"    //  num, err = Ormer.Update(&user, "Langs", "Extra")    Update(md interface{}, cols ...string) (int64, error)    // delete model in database    Delete(md interface{}, cols ...string) (int64, error)    // load related models to md model.    // args are limit, offset int and order string.    //    // example:    //  Ormer.LoadRelated(post,"Tags")    //  for _,tag := range post.Tags{...}    //args[0] bool true useDefaultRelsDepth ; false  depth 0    //args[0] int  loadRelationDepth    //args[1] int limit default limit 1000    //args[2] int offset default offset 0    //args[3] string order  for example : "-Id"    // make sure the relation is defined in model struct tags.    LoadRelated(md interface{}, name string, args ...interface{}) (int64, error)    // create a models to models queryer    // for example:    //  post := Post{Id: 4}    //  m2m := Ormer.QueryM2M(&post, "Tags")    QueryM2M(md interface{}, name string) QueryM2Mer    // return a QuerySeter for table operations.    // table name can be string or struct.    // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),    QueryTable(ptrStructOrTableName interface{}) QuerySeter    // switch to another registered database driver by given name.    Using(name string) error    // begin transaction    // for example:    //  o := NewOrm()    //  err := o.Begin()    //  ...    //  err = o.Rollback()    Begin() error    // commit transaction    Commit() error    // rollback transaction    Rollback() error    // return a raw query seter for raw sql string.    // for example:    //   ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec()    //  // update user testing's name to slene    Raw(query string, args ...interface{}) RawSeter    Driver() Driver}

QueryTable

傳入表名,或者 Model 對象,返回一個 QuerySeter

o := orm.NewOrm()var qs QuerySeterqs = o.QueryTable("user")// 如果表沒有定義過,會立刻 panic

Using

切換為其他資料庫

orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8")orm.RegisterDataBase("db2", "sqlite3", "data.db")o1 := orm.NewOrm()o1.Using("db1")o2 := orm.NewOrm()o2.Using("db2")// 切換為其他資料庫以後// 這個 Ormer 對象的其下的 api 調用都將使用這個資料庫

預設使用 default 資料庫,無需調用 Using

Raw

使用 sql 語句直接進行操作

Raw 函數,返回一個 RawSeter 用以對設定的 sql 語句和參數進行操作

o := NewOrm()var r RawSeterr = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")

Driver

返回當前 ORM 使用的 db 資訊

type Driver interface {    Name() string    Type() DriverType}
orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8")orm.RegisterDataBase("db2", "sqlite3", "data.db")o1 := orm.NewOrm()o1.Using("db1")dr := o1.Driver()fmt.Println(dr.Name() == "db1") // truefmt.Println(dr.Type() == orm.DRMySQL) // trueo2 := orm.NewOrm()o2.Using("db2")dr = o2.Driver()fmt.Println(dr.Name() == "db2") // truefmt.Println(dr.Type() == orm.DRSqlite) // true

偵錯模式列印查詢語句

簡單的設定 Debug 為 true 列印查詢的語句

可能存在效能問題,不建議使用在生產模式

func main() {    orm.Debug = true...

預設使用 os.Stderr 輸出日誌資訊

改變輸出到你自己的 io.Writer

var w io.Writer...// 設定為你的 io.Writer...orm.DebugLog = orm.NewLog(w)
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.