Zorm之國產(chǎn)化數(shù)據(jù)庫實踐

簡介

go(golang)輕量級ORM,零依賴,支持達夢(dm),金倉(kingbase),神通(shentong),南大通用(gbase),mysql,postgresql,oracle,mssql,sqlite數(shù)據(jù)庫.
源碼地址:https://gitee.com/chunanyong/zorm
作者博客:https://www.jiagou.com

實踐項目

夜鶯監(jiān)控告警項目國產(chǎn)化數(shù)據(jù)庫的支持
夜鶯是一套滴滴團隊主導開源的分布式高可用的運維監(jiān)控系統(tǒng)蝗岖。
源碼地址:https://github.com/didi/nightingale

改造方案

夜鶯使用的是xorm作為ORM庫,不支持國產(chǎn)數(shù)據(jù)庫斗锭。嘗試過通過ODBC的方式連接達夢摊册,操作時遇到了語法不兼容問題嗜暴。之后又了解到zorm耸棒,這個本身天然支持國產(chǎn)數(shù)據(jù)庫的ORM框架。
面前出現(xiàn)了兩種選擇: 一是繼續(xù)嘗試ODBC的方式橡淆,一庫一庫的調(diào)試,手動解決各種兼容問題母赵。二是替換項目的orm庫逸爵,改造一次,就可以把國產(chǎn)四庫的支持全部搞定凹嘲。想想還是后者比較香师倔,改造走起!

改造過程

首先數(shù)據(jù)庫初始化周蹭,夜鶯項目有多個數(shù)據(jù)庫

//聲明存儲多庫連接信息的map趋艘,key是dbname疲恢,value是DBDao
var DB = map[string]*zorm.DBDao{}

func InitMySQL(names ...string) {
        //讀取mysql.yml數(shù)據(jù)庫配置文件
    confdir := path.Join(runner.Cwd, "etc")
    mysqlYml := path.Join(confdir, "mysql.local.yml")
    if !file.IsExist(mysqlYml) {
        mysqlYml = path.Join(confdir, "mysql.yml")
    }

    confs := make(map[string]MySQLConf)
    err := file.ReadYaml(mysqlYml, &confs)
    if err != nil {
        log.Fatalf("cannot read yml[%s]: %v", mysqlYml, err)
    }
        //多庫,不同的name
    count := len(names)
    for i := 0; i < count; i++ {
        conf, has := confs[names[i]]
        if !has {
            log.Fatalf("no such mysql conf: %s", names[i])
        }

        dbDaoConfig := zorm.DataSourceConfig{
            //DSN 數(shù)據(jù)庫的連接字符串
            DSN: conf.Addr,
            //數(shù)據(jù)庫驅(qū)動名稱:mysql,postgres,oci8,sqlserver,sqlite3,dm,kingbase 和DBType對應(yīng),處理數(shù)據(jù)庫有多個驅(qū)動
            DriverName: "kingbase",
            //數(shù)據(jù)庫類型(方言判斷依據(jù)):mysql,postgresql,oracle,mssql,sqlite,dm,kingbase 和 DriverName 對應(yīng),處理數(shù)據(jù)庫有多個驅(qū)動
            DBType: "kingbase",
            //MaxOpenConns 數(shù)據(jù)庫最大連接數(shù) 默認50
            MaxOpenConns: 50,
            //MaxIdleConns 數(shù)據(jù)庫最大空閑連接數(shù) 默認50
            MaxIdleConns: 50,
            //ConnMaxLifetimeSecond 連接存活秒時間. 默認600(10分鐘)后連接被銷毀重建.避免數(shù)據(jù)庫主動斷開連接,造成死連接.MySQL默認wait_timeout 28800秒(8小時)
            ConnMaxLifetimeSecond: 600,
            //PrintSQL 打印SQL.會使用FuncPrintSQL記錄SQL
            PrintSQL: conf.Debug,
        }
    
        // 根據(jù)dbDaoConfig創(chuàng)建dbDao, 一個數(shù)據(jù)庫只執(zhí)行一次,第一個執(zhí)行的數(shù)據(jù)庫為 defaultDao,后續(xù)zorm.xxx方法,默認使用的就是defaultDao
        dbDao, _ := zorm.NewDBDao(&dbDaoConfig)
        DB[names[i]] = dbDao
    }
}

建立連接
通過傳入不同的dbName 獲取綁定連接的Ctx

func getNewCtx(dbName string) context.Context {
    var ctx = context.Background()
    var dbDao *zorm.DBDao = DB[dbName]
        
    newCtx, err := dbDao.BindContextDBConnection(ctx)
    if err != nil { //標記測試失敗
        log.Fatalf("錯誤:%v", err)
    }

    return newCtx
}

操作
zorm還有一個方便實用的點:

  1. 在codeGenerator.go 中配置好數(shù)據(jù)庫的連接信息
  2. 如果只想初始化單張表致稀,請修改codeGenerator_test.go 中TestCodeGenerator調(diào)用的code參數(shù)冈闭,為表名
  3. 單表初始化:執(zhí)行g(shù)o test -v codeGenerator_test.go codeGenerator.go -test.run TestCodeGenerator
    整個庫初始化:執(zhí)行g(shù)o test -v codeGenerator_test.go codeGenerator.go -test.run TestCodeGeneratorALL

生成器代碼簡單清晰俱尼,可根據(jù)自己的需求做一些調(diào)整抖单,使最終生成的代碼能一步到位。

生成效果
拿一個表舉例

//table name
const NodeStructTableName = "node"

// NodeStruct
type Node struct {
    zorm.EntityStruct
    Id int64 `column:"id" json:"id"`
    Pid int64 `column:"pid" json:"pid"`
    Name string `column:"name" json:"name"`
    Path string `column:"path" json:"path"`
    Leaf int `column:"leaf" json:"leaf"`
    Note string `column:"note" json:"note"`

}

func (entity *Node) GetTableName() string {
    return NodeStructTableName
}

//GetPKColumnName 獲取數(shù)據(jù)庫表的主鍵字段名稱.因為要兼容Map,只能是數(shù)據(jù)庫的字段名稱.
func (entity *Node) GetPKColumnName() string {
    return "id"
}

增刪改查
使用原生的sql語句,沒有對sql語法做限制.語句使用Finder作為載體

    //查詢
    var obj Node
    //has, err := DB["mon"].Where(col+"=?", val).Get(&obj)  這是之前xorm的代碼
    //獲取對應(yīng)數(shù)據(jù)庫的連接
    newCtx := getNewCtx("mon")
    finder := zorm.NewSelectFinder(NodeStructTableName) 
    finder.Append("WHERE "+col+"=?", val)
    has, err := zorm.QueryRow(newCtx, finder, &obj)



  //添加
    node := Node{
        Pid:  0,
        Name: "cop",
        Path: "cop",
        Leaf: 0,
        Note: "公司節(jié)點",
    }
    //_, err = DB["mon"].Insert(&node)  這是之前xorm的代碼
    //手動開啟事務(wù),匿名函數(shù)返回的error如果不是nil,事務(wù)就會回滾
    _, err = zorm.Transaction(newCtx, func(newCtx context.Context) (interface{}, error) {
        //具體操作
        _, err = zorm.Insert(newCtx, &node)
        return nil, err
    })
    
    if err != nil {
        log.Fatalln("cannot insert node[cop]")
    }


    //修改
    newCtx := getNewCtx("mon")
    //手動開啟事務(wù),匿名函數(shù)返回的error如果不是nil,事務(wù)就會回滾
    _, err := zorm.Transaction(newCtx, func(newCtx context.Context) (interface{}, error) {
        _, err := zorm.Update(newCtx, obj)
        //如果返回的err不是nil,事務(wù)就會回滾
        return nil, err

    })
      

    //刪除
    //_, err := DB["mon"].Where("id=?", n.Id).Delete(new(Node))
    //手動開啟事務(wù),匿名函數(shù)返回的error如果不是nil,事務(wù)就會回滾
    _, err := zorm.Transaction(newCtx, func(newCtx context.Context) (interface{}, error) {
        finder := zorm.NewDeleteFinder(NodeStructTableName)
        finder.Append("WHERE id=?", n.Id)
        _, err := zorm.UpdateFinder(newCtx, finder)
        return nil, err
    })

改造總結(jié)

zorm上手非常簡單遇八,改造過程也很順暢矛绘。
以上只是zorm使用的部分示例,除此之外zorm還支持事務(wù)傳播刃永、批量操作货矮、不方便使用struct的場景,以及讀寫分離等斯够。更多使用場景請前往 zorm官方囚玫。
如有使用方面的疑問請下方留言,改造建議或想了解更多读规,請在最上方源碼地址找官方抓督,作者回復(fù)也很熱情: )

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市束亏,隨后出現(xiàn)的幾起案子铃在,更是在濱河造成了極大的恐慌,老刑警劉巖碍遍,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件定铜,死亡現(xiàn)場離奇詭異,居然都是意外死亡怕敬,警方通過查閱死者的電腦和手機揣炕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來东跪,“玉大人祝沸,你說我怎么就攤上這事≡奖樱” “怎么了罩锐?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長卤唉。 經(jīng)常有香客問我涩惑,道長,這世上最難降的妖魔是什么桑驱? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任竭恬,我火速辦了婚禮跛蛋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘痊硕。我一直安慰自己赊级,他們只是感情好,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布岔绸。 她就那樣靜靜地躺著理逊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盒揉。 梳的紋絲不亂的頭發(fā)上晋被,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天,我揣著相機與錄音刚盈,去河邊找鬼羡洛。 笑死,一個胖子當著我的面吹牛藕漱,可吹牛的內(nèi)容都是我干的欲侮。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼肋联,長吁一口氣:“原來是場噩夢啊……” “哼威蕉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起牺蹄,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤忘伞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沙兰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氓奈,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年鼎天,在試婚紗的時候發(fā)現(xiàn)自己被綠了舀奶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡斋射,死狀恐怖育勺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情罗岖,我是刑警寧澤涧至,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站桑包,受9級特大地震影響南蓬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一赘方、第九天 我趴在偏房一處隱蔽的房頂上張望烧颖。 院中可真熱鬧,春花似錦窄陡、人聲如沸炕淮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涂圆。三九已至,卻和暖如春优妙,著一層夾襖步出監(jiān)牢的瞬間乘综,已是汗流浹背憎账。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工套硼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胞皱。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓邪意,卻偏偏與公主長得像,于是被迫代替她去往敵國和親反砌。 傳聞我的和親對象是個殘疾皇子雾鬼,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容