Go實戰專案-Beego的orm的基本使用

棋佈發表於2020-10-17

beego的使用三部曲:
1、在controllers裡面建立控制器
2、在module裡面建立資料模型
3、在router設定路由控制
對於beego的orm使用有很多種方式,我們主要採用過濾器的方式來實現。因為前面說過,嚴禁使用原生的sql語句。

依然三部曲:
1、建立模型
2、註冊模型
3、使用模型獲取資料

//注意表和列的命名規則
type CLogin struct {
    Id             int       `orm:"column(id)" json:"id"`
    LoginId        string    `orm:"column(LoginId)" json:"LoginId"`
    Pwd            string    `orm:"column(Pwd)" json:"Pwd"`
    FullName       string    `orm:"column(FullName)" json:"FullName"`
    DepartmentId   int       `orm:"column(DepartmentId)" json:"DepartmentId"`
    DepartmentName string    `orm:"column(DepartmentName)" json:"DepartmentName"`
    RoleId         int       `orm:"column(role_id)" json:"role_id"`
    Deleted        int       `orm:"column(deleted)" json:"deleted"`
    Telephone      string    `orm:"column(telephone)" json:"telephone"`
    IdCard         string    `orm:"column(id_card)" json:"id_card"`
    JobCard        string    `orm:"column(job_card)" json:"job_card"`
    EnterpriseId   int64     `orm:"column(enterpriseId)" json:"enterpriseId"`
    UpdateTime     time.Time `orm:"type(datetime);column(update_time)" json:"update_time"` //date  這些tag可以透過反射來自己實現
    //CRole          *CRoles `orm:"rel(one)" json:"role"`
}

站在這裡就有int,string,date格式的表述,其他型別,都是一次類推,特殊型別的,可以用type指定,如orm:”type(datetime);column(update_time)

單表查詢的一種方式,僅僅作為演示:

    o := orm.NewOrm()
    user = CLogin{LoginId: loginId}
    err = o.Read(&user, "LoginId")
    //多條件不能這麼寫,這樣獲取不到資料
    //user = CLogin{LoginId: loginId, Pwd: md5Pwd}

注意,這種方式只能匹配第一引數,後面新增了也不會識別,不知道是不是我使用的問題還是怎麼回事,我們的重點也不在這,由於此專案沒有外來鍵,無法進行模型關聯查詢,所以只能捨棄這種方式的研究,採用過濾器的方式。當然,還有build的方式來實現,可以參考官網自己實現。

//採用過濾器QuerySeter實現
err = o.QueryTable(“c_login”).Filter(“LoginId”,loginId).Filter(“pwd”,pwd).One(&user)
不定項條件查詢:

//不定項多條件查詢
querySet := o.QueryTable("c_login")
querySet = querySet.Filter("LoginId", loginId)
if pwd != "123456" {
    querySet = querySet.Filter("pwd", pwd)
}
err = querySet.One(&user)

注意,不能採用鏈式直連的方式,如果去掉多次賦值的話,前面的條件都不會生效,因為在他是採用值複製的方式傳遞的,並非採用引用傳遞的。

前面有說到,建立模型可以直接正在做到關聯查詢,前提是必須要有外來鍵的存在,前人制造的表結構,我們也不好意思評價,這恰恰可以給我們成長提供機會。所以,我採用的是raw,採用佔位符的方式,否則就需要建立外來鍵和對應的外來鍵id,否則會報錯提是找不到外來鍵id。

//獲取角色許可權
func GetRoleSession(roleId int) ([]orm.Params, error) {
    var (
        err  error
        maps []orm.Params
    )
    o := orm.NewOrm()
    _, err = o.Raw("select p.id,p.url,p.name, p.code,1 as checked from c_role_power as r join c_power as p on r.pid = p.id where r.rid=?", roleId).Values(&maps)
    return maps, err
}

querySeter的其他操作,可以仿照查詢的條件新增方式進行操作。可以hi姐實現。比如:

//更新c_login表
func LoginUpdate(id int, pwd string) error {
    o := orm.NewOrm()
    querySetter := o.QueryTable("c_login")
    querySetter = querySetter.Filter("id", id)
    params := make(map[string]interface{})
    params["id"] = id
    params["Pwd"] = utils.Md5(pwd)
    params["update_time"] = time.Now().Format("2006-01-02 15:04:05")
    fmt.Println("params", params)
    _, err := querySetter.Update(params)
    return err
}

Update(values Params) (int64, error)
Delete() (int64, error)
PrepareInsert() (Inserter, error)
Exist() bool :判斷表書否存在,這個對於私有化部署,程式碼新增新表做升級處理方便直接的多。

別忘了,還有註冊結構模型

    orm.RegisterModel(new(CLogin), new(CRoles))
    //orm.RegisterModelWithPrefix("c_", new(Roles))

除了直接登錄檔名規範之外,還有字首的方式新增, 這樣結構體的名字就不會這麼的噁心了。

這個多庫的比較麻煩,必須要註冊資料庫,並且要設定別名,後續的使用也是必須使用別名來呼叫資料庫才能生效。直接貼上工具類:

//Use "callout" db "default" as alias name if you not set.
func GetOrm(dbName ...string) (orm.Ormer, error) {
    var (
        alias      string
        tempDbName string
        err        error
    )
    if len(dbName) > 0 {
        tempDbName = dbName[0]
    } else {
        tempDbName = "callout"
    }
    o := orm.NewOrm()
    if tempDbName == "callout" {
        alias = "default"
    } else if tempDbName == "default" {
        alias = "default"
    } else if !strings.HasPrefix(tempDbName, "co") {
        alias = "co" + tempDbName
    } else {
        alias = "default"
    }

    logs.Info("alias: ", alias)
    err = o.Using(alias) //這裡使用的是資料庫的別名,不是直接連線資料庫
    logs.Info("using alias err: ", err)
    if err != nil { //代表沒有這個別名的資料庫,需要註冊
        registerDatabases(alias)
        err = o.Using(alias)
        logs.Info("using alias against err: ", err)
    }
    return o, err
}

//初始化設定資料庫,註冊一個預設的資料庫,並設定最大連線數和最大空閒數
func InitBeeGoOrm() {
    defaultDB := beego.AppConfig.String("defaultDB") //app.conf檔案配置
    err := orm.RegisterDriver("mysql", orm.DRMySQL)
    if err != nil {
        fmt.Println("RegisterDriver err: ", err)
    }
    // 引數1        資料庫的別名,用來在 ORM 中切換資料庫使用
    // 引數2        driverName
    // 引數3        對應的連結字串
    // 引數4(可選)  設定最大空閒連線
    // 引數5(可選)  設定最大資料庫連線 (go >= 1.2)
    err = orm.RegisterDataBase("default", "mysql", defaultDB, 50, 100) //暫時寫死,可以寫成動態的
    if err != nil {
        fmt.Println("RegisterDataBase err: ", err)
    }
}

//註冊資料庫
func registerDatabases(dbName string) {
    mySqlUser := beego.AppConfig.String("mySqlUser")
    mySqlPwd := beego.AppConfig.String("mySqlPwd")
    mySqlAddress := beego.AppConfig.String("mySqlAddress")
    fmt.Println("RegisterDataBase: ", mySqlUser, mySqlPwd, mySqlAddress)
    defaultDB := fmt.Sprintf("%s:%s@(%s)/%s?timeout=30s&charset=utf8mb4&collation=utf8mb4_general_ci", mySqlUser, mySqlPwd, mySqlAddress, dbName)
    fmt.Println("RegisterDataBase defaultDB: ", defaultDB)
    err := orm.RegisterDataBase(dbName, "mysql", defaultDB, 50, 100)
    if err != nil {
        fmt.Println("RegisterDataBase err: ", err)
    }
}

多庫之間的別名,我採用的是資料庫名作為別名,這樣方便註冊和使用。但是,預設的是資料庫只能是default,這個有點耍流氓了。但是,不影響我們封裝起來,只是一個判斷的問題。後續的使用也方便,只需要把o, err = utils.GetOrm(strEnterprise)替換掉o := orm.NewOrm()就可以了直接使用了。至於池的概念,那就是使用框架自身的,在函式InitBeeGoOrm裡面就有設定。空閒數和連線數,依然按照之前的方式來除錯設定。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
歡迎轉載分享提意見,一起code

相關文章