gf架構之gdb - 優雅強大的資料庫ORM

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

gf架構的資料庫ORM操作由gdb包提供支援,gdb包經過非常精心優雅的設計,提供了非常強大的組態管理、方法操作、鏈式操作、事務操作等功能。gdb包具體API說明文檔詳見:godoc 。本章節對gdb包的使用進行基本的介紹,包括:gdb包準系統介紹,組態管理功能說明,常見用法及常用操作樣本。

使用方式:

import "gitee.com/johng/gf/g/database/gdb"

資料庫配置

gdb資料結構:

type List        []Map                  // 資料記錄列表 type Map         map[string]interface{} // 資料記錄type Config      map[string]ConfigGroup // 資料庫設定物件type ConfigGroup []ConfigNode           // 資料庫分組配置// 資料庫配置項(一個分組配置對應多個配置項)type ConfigNode  struct {    Host     string // 地址    Port     string // 連接埠    User     string // 帳號    Pass     string // 密碼    Name     string // 資料庫名稱    Type     string // 資料庫類型:mysql, sqlite, mssql, pgsql, oracle(目前僅支援mysql,pgsql)    Role     string // (可選,預設為master)資料庫的角色,用於主從操作分離,至少需要有一個master,參數值:master, slave    Charset  string // (可選,預設為 utf-8)編碼,預設為 utf-8    Priority int    // (可選)用於負載平衡的權重計算,當叢集中只有一個節點時,權重沒有任何意義    Linkinfo string // (可選)自訂連結資訊,當該欄位被設定值時,以上連結欄位(Host,Port,User,Pass,Name)將失效(該欄位是一個擴充功能,參考sql.Open參數)}

其中,Map和List用於資料表記錄操作,分別對應一條資料表記錄和資料表記錄列表;Config、ConfigGroup及ConfigNode用於資料庫組態管理,ConfigNode用於儲存一個資料庫節點資訊,ConfigGroup用於管理多個資料庫節點群組成的配置分組(一般一個分組對應一個業務資料庫叢集),Config用於管理多個ConfigGroup配置分組。

gdb主要特點:

  1. 支援多節點資料庫叢集管理,採用單例模式管理資料庫執行個體化對象;
  2. 支援對資料庫叢集分組管理,按照分組名稱擷取執行個體化的資料庫操作對象;
  3. 支援多種關係型資料庫管理,可通過ConfigNode.Type屬性進行配置(目前僅支援mysql和pgsql資料庫);
  4. 支援Master-Slave讀寫分離,可通過ConfigNode.Role屬性進行配置;
  5. 支援用戶端的負載平衡管理,可通過ConfigNode.Priority屬性進行配置,值越大,優先順序越高;

特別說明,gdb的組態管理最大的特點是,(同一進程中)所有的資料庫叢集資訊都使用同一個組態管理模組進行統一維護,不同業務的資料庫叢集配置使用不同的分組名稱進行配置和擷取。

配置方法

資料庫組態管理方法列表:

// 添加一個資料庫節點到指定的分組中func AddConfigNode(group string, node ConfigNode)// 添加一個配置分組到資料庫組態管理中(同名覆蓋)func AddConfigGroup(group string, nodes ConfigGroup)// 添加一個資料庫節點到預設的分組中(預設為default,可修改)func AddDefaultConfigNode(node ConfigNode)// 添加一個配置分組到資料庫組態管理中(預設分組為default,可修改)func AddDefaultConfigGroup(nodes ConfigGroup)// 設定資料庫配置為定義的配置資訊func SetConfig(c Config)// 設定預設的分組名稱func SetDefaultGroup(groupName string)

預設分組表示,如果擷取資料庫物件時不指定配置分組名稱,那麼gdb預設讀取的配置分組。例如:gdb.Instance()可擷取一個預設分組的資料庫單例對象。

簡單的做法,我們可以通過gdb包的SetConfig組態管理方法進行自訂的資料庫全域配置,例如:

gdb.SetConfig(gdb.Config {    "default" : gdb.ConfigGroup {        gdb.ConfigNode {            Host     : "127.0.0.1",            Port     : "3306",            User     : "root",            Pass     : "123456",            Name     : "test",            Type     : "mysql",            Role     : "master",            Priority : 100,        },        gdb.ConfigNode {            Host     : "127.0.0.2",            Port     : "3306",            User     : "root",            Pass     : "123456",            Name     : "test",            Type     : "mysql",            Role     : "master",            Priority : 100,        },    },})

設定檔

當然,gdb支援設定檔進行配置,這樣也便於項目的組態管理,具體請參見【ORM進階用法】章節。

資料庫操作

gdb資料庫操作的方法比較多,具體詳見godoc,以下僅對一些常用的方法進行介紹。

方法操作

// SQL操作方法,返回原生的標準庫sql對象Query(query string, args ...interface{}) (*sql.Rows, error)Exec(query string, args ...interface{}) (sql.Result, error)Prepare(query string) (*sql.Stmt, error)// 資料表記錄查詢:// 查詢單條記錄、查詢多條記錄、查詢單個欄位值(鏈式操作同理)GetAll(query string, args ...interface{}) (List, error)GetOne(query string, args ...interface{}) (Map, error)GetValue(query string, args ...interface{}) (interface{}, error)// 開啟事務操作Begin() (*Tx, error)// 資料單條操作Insert(table string, data Map) (sql.Result, error)Replace(table string, data Map) (sql.Result, error)Save(table string, data Map) (sql.Result, error)// 資料大量操作BatchInsert(table string, list List, batch int) (sql.Result, error)BatchReplace(table string, list List, batch int) (sql.Result, error)BatchSave(table string, list List, batch int) (sql.Result, error)// 資料修改/刪除Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error)Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error)// 建立鏈式操作對象(Table為From的別名)Table(tables string) (*DbOp)From(tables string) (*DbOp)    // 關閉資料庫Close() error

需要說明一下Insert/Replace/Save三者的區別(BatchInsert/BatchReplace/BatchSave同理):

  1. Insert:使用insert into語句進行資料庫寫入,如果寫入的資料中存在Primary Key或者Unique Key的情況,返回失敗,否則寫入一條新資料;
  2. Replace:使用replace into語句進行資料庫寫入,如果寫入的資料中存在Primary Key或者Unique Key的情況,刪除原有記錄,按照給定資料新寫入一條新記錄,否則寫入一條新資料;
  3. Save:使用insert into語句進行資料庫寫入,如果寫入的資料中存在Primary Key或者Unique Key的情況,更新原有資料,否則寫入一條新資料;

鏈式操作

gdb提供簡便靈活的鏈式操作介面,通過資料庫物件的db.Table/db.From方法或者事務對象的tx.Table/tx.From方法基於指定的資料表返回一個鏈式操作對象DbOp,該對象可以執行以下方法(具體方法說明請參考API文檔)。

func LeftJoin(joinTable string, on string) (*DbOp)func RightJoin(joinTable string, on string) (*DbOp)func InnerJoin(joinTable string, on string) (*DbOp)func Fields(fields string) (*DbOp)func Limit(start int, limit int) (*DbOp)func Data(data interface{}) (*DbOp)func Batch(batch int) *DbOpfunc Where(where string, args...interface{}) (*DbOp)func GroupBy(groupby string) (*DbOp)func OrderBy(orderby string) (*DbOp)func Insert() (sql.Result, error)func Replace() (sql.Result, error)func Save() (sql.Result, error)func Update() (sql.Result, error)func Delete() (sql.Result, error)func Select() (List, error)func All() (List, error)func One() (Map, error)func Value() (interface{}, error)

資料庫樣本

https://gitee.com/johng/gf/bl...

方法操作

  1. 擷取ORM單例對象

    // 擷取預設配置的資料庫物件(配置名稱為"default")db, err := gdb.Instance()// 擷取配置分組名稱為"user-center"的資料庫物件db, err := gdb.Instance("user-center")
  2. 資料寫入

    r, err := db.Insert("user", gdb.Map {    "name": "john",})
  3. 資料查詢(列表)

    list, err := db.GetAll("select * from user limit 2")
  4. 資料查詢(單條)

    one, err := db.GetOne("select * from user limit 2")// 或者one, err := db.GetOne("select * from user where uid=1000")
  5. 資料儲存

    r, err := db.Save("user", gdb.Map {    "uid"  :  1,    "name" : "john",})
  6. 大量操作

    // BatchInsert/BatchReplace/BatchSave 同理_, err := db.BatchInsert("user", gdb.List {    {"name": "john_1"},    {"name": "john_2"},    {"name": "john_3"},    {"name": "john_4"},}, 10)
  7. 資料更新/刪除

    // db.Update/db.Delete 同理r, err := db.Update("user", gdb.Map {"name": "john"}, "uid=?", 10000)r, err := db.Update("user", "name='john'", "uid=10000")r, err := db.Update("user", "name=?", "uid=?", "john", 10000)

    注意,參數域支援並建議使用預先處理模式進行輸入,避免SQL注入風險。

鏈式操作

  1. 鏈式查詢

    // 查詢多條記錄並使用Limit分頁r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*, ud.site").Where("u.uid > ?", 1).Limit(0, 10).Select()// 查詢合格單條記錄(第一條)r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.site").Where("u.uid=?", 1).One()// 查詢欄位值r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("ud.site").Where("u.uid=?", 1).Value()// 分組及排序r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.city").GroupBy("city").OrderBy("register_time asc").Select()
  2. 鏈式更新/刪除

    // 更新r, err := db.Table("user").Data(gdb.Map{"name" : "john2"}).Where("name=?", "john").Update()r, err := db.Table("user").Data("name='john3'").Where("name=?", "john2").Update()// 刪除r, err := db.Table("user").Where("uid=?", 10).Delete()
  3. 鏈式寫入/儲存

    r, err := db.Table("user").Data(gdb.Map{"name": "john"}).Insert()r, err := db.Table("user").Data(gdb.Map{"uid": 10000, "name": "john"}).Replace()r, err := db.Table("user").Data(gdb.Map{"uid": 10001, "name": "john"}).Save()
  4. 鏈式批量寫入

    r, err := db.Table("user").Data(gdb.List{    {"name": "john_1"},    {"name": "john_2"},    {"name": "john_3"},    {"name": "john_4"},}).Insert()

    可以指定大量操作中分批寫入資料庫的每批次寫入條數數量:

    r, err := db.Table("user").Data(gdb.List{    {"name": "john_1"},    {"name": "john_2"},    {"name": "john_3"},    {"name": "john_4"},}).Batch(2).Insert()
  5. 鏈式批量儲存

    r, err := db.Table("user").Data(gdb.List{    {"uid":10000, "name": "john_1"},    {"uid":10001, "name": "john_2"},    {"uid":10002, "name": "john_3"},    {"uid":10003, "name": "john_4"},}).Save()

事務操作

開啟事務操作可以通過執行db.Begin方法,該方法返回事務的操作對象,類型為*gdb.Tx,通過該對象執行後續的資料庫操作,並可通過tx.Commit提交修改,或者通過tx.Rollback復原修改。

  1. 開啟事務操作

    if tx, err := db.Begin(); err == nil {    fmt.Println("開啟事務操作")}

    事務操作對象可以執行所有db對象的方法,具體請參考API文檔。

  2. 交易回復操作

    if tx, err := db.Begin(); err == nil {    r, err := tx.Save("user", gdb.Map{        "uid"  :  1,        "name" : "john",    })    tx.Rollback()    fmt.Println(r, err)}
  3. 事務提交操作

    if tx, err := db.Begin(); err == nil {    r, err := tx.Save("user", gdb.Map{        "uid"  :  1,        "name" : "john",    })    tx.Commit()    fmt.Println(r, err)}
  4. 事務鏈式操作
    事務操作對象仍然可以通過tx.Table或者tx.From方法返回一個鏈式操作的對象,該對象與db.Table或者db.From方法傳回值相同,只不過資料庫操作在事務上執行,可提交或復原。

    if tx, err := db.Begin(); err == nil {    r, err := tx.Table("user").Data(gdb.Map{"uid":1, "name": "john_1"}).Save()    tx.Commit()    fmt.Println(r, err)}

    其他鏈式操作請參考上述鏈式操作章節。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.