Goframe數據庫操作

Goframe數據庫操作

一、基本介紹

gf框架的ORM功能由gdb模塊實現,用於常用關係型數據庫的ORM操作。其最大的特色在於同時支持mapstruct兩種方式操作數據庫。gdb默認情況下使用的是map數據類型作爲基礎的數據表記錄載體,開發者無需預先定義數據表記錄struct便可直接對數據表記錄執行各種操作。這樣的設計賦予了開發者更高的靈活度和簡便性。

支持的數據庫類型:Mysql,SQLite,PostgreSQL,SQLServer,Oracle

二、配置文件

推薦使用配置文件及單例對象來管理和使用數據庫操作。

如果我們使用g對象管理模塊中的g.DB("數據庫分組名稱")方法獲取數據庫操作對象,數據庫對象將會自動讀取config.toml配置文件中的相應配置項(通過配置管理模塊),並自動初始化該數據庫操作的單例對象。

[database]
    [[database.default]]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
    [[database.user]]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/user"

注意每一項分組配置均可以是多個節點,支持負載均衡權重策略。如果不使用多節點負載均衡特性,僅使用配置分組特性,也可以簡化爲如下格式:

[database]
    [database.default]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
    [database.user]
        link = "mysql:root:12345678@tcp(127.0.0.1:3306)/user"

如果僅僅是單數據庫節點,不使用配置分組特性,那麼也可以簡化爲如下格式:

[database]
    link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"

不同數據類型對應的linkinfo如下:

數據庫類型 Linkinfo配置 更多參數
mysql mysql: 賬號:密碼@tcp(地址:端口)/數據庫名稱 mysql
pgsql pgsql: user=賬號 password=密碼 host=地址 port=端口 dbname=數據庫名稱 pq
mssql mssql: user id=賬號;password=密碼;server=地址;port=端口;database=數據庫名稱;encrypt=disable go-mssqldb
sqlite sqlite: 文件絕對路徑 (如: /var/lib/db.sqlite3) go-sqlite3
oracle oracle: 賬號/密碼@地址:端口/數據庫名稱 go-oci8

三、日誌輸出配置

gdb支持日誌輸出,內部使用的是glog.Logger對象實現日誌管理,並且可以通過配置文件對日誌對象進行配置。默認情況下gdb關閉了DEBUG日誌輸出,如果需要打開DEBUG信息需要將數據庫的debug參數設置爲true。以下是爲一個配置文件示例:

[database]
    [database.logger]
        Path   = "/var/log/gf-app/sql"
        Level  = "all"
        Stdout = true
    [database.primary]
        link   = "mysql:root:12345678@tcp(127.0.0.1:3306)/user_center"
        debug  = true

其中database.logger即爲gdb的日誌配置,當該配置不存在時,將會使用日誌組件的默認配置

四、數據結構

爲便於數據表記錄的操作,ORM定義了5種基本的數據類型:

type Map         map[string]interface{} // 數據記錄
type List        []Map                  // 數據記錄列表

type Value       *gvar.Var              // 返回數據表記錄值
type Record      map[string]Value       // 返回數據表記錄鍵值對
type Result      []Record               // 返回數據表記錄列表
  1. MapList用於ORM操作過程中的輸入參數類型(與全局類型g.Mapg.List一致,在項目開發中常用g.Mapg.List替換);
  2. Value/Record/Result用於ORM操作的結果數據類型;

五、數據庫操作

Insert/Replace/Save

這三個鏈式操作方法用於數據的寫入,並且支持自動的單條或者批量的數據寫入,三者區別如下:

  1. Insert

    使用INSERT INTO語句進行數據庫寫入,如果寫入的數據中存在主鍵或者唯一索引時,返回失敗,否則寫入一條新數據;

  2. Replace

    使用REPLACE INTO語句進行數據庫寫入,如果寫入的數據中存在主鍵或者唯一索引時,會刪除原有的記錄,必定會寫入一條新記錄;

  3. Save

    使用INSERT INTO語句進行數據庫寫入,如果寫入的數據中存在主鍵或者唯一索引時,更新原有數據,否則寫入一條新數據;

在部分數據庫類型中,並不支持Replace/Save方法

Update更新方法

Update用於數據的更新,往往需要結合DataWhere方法共同使用。Data方法用於指定需要更新的數據,Where方法用於指定更新的條件範圍。同時,Update方法也支持直接給定數據和條件參數。

Delete刪除方法

Delete方法用於數據的刪除。

Where/And/Or查詢條件

這三個方法用於傳遞查詢條件參數,支持的參數爲任意的string/map/slice/struct/*struct類型。

Where條件參數推薦使用字符串的參數傳遞方式(並使用?佔位符預處理),因爲map/struct類型作爲查詢參數無法保證順序性,且在部分情況下(數據庫有時會幫助你自動進行查詢索引優化),數據庫的索引和你傳遞的查詢條件順序有一定關係。

當使用多個Where方法連接查詢條件時,作用同And。 此外,當存在多個查詢條件時,gdb會默認將多個條件分別使用()符號進行包含,這種設計可以非常友好地支持查詢條件分組。

All/One/Value/Count數據查詢

這四個方法是數據查詢比較常用的方法:

  1. All 用於查詢並返回多條記錄的列表/數組。
  2. One 用於查詢並返回單條記錄。
  3. Value 用於查詢並返回一個字段值,往往需要結合Fields方法使用。
  4. Count 用於查詢並返回記錄數。

此外,也可以看得到這四個方法定義中也支持條件參數的直接輸入,參數類型與Where方法一致。但需要注意,其中Value方法的參數中至少應該輸入字段參數。

數據庫表

CREATE TABLE `user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `site` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=10000 ;

示例

package test

import (
   "fmt"
   "github.com/gogf/gf/frame/g"
   "testing"
)

// Insert
func TestInsert(t *testing.T) {
   // INSERT INTO `user`(`name`) VALUES('john')
   _, err := g.DB().Model("user").Data(g.Map{"uid": 10000, "name": "john"}).Insert()
   if err != nil {
      panic(err)
   }
}

// Update
func TestUpdate(t *testing.T) {
   // UPDATE `user` SET `name`='john guo' WHERE name='john'
   _, err := g.DB().Model("user").Data("name", "john guo").
      Where("name", "john").Update()
   if err != nil {
      panic(err)
   }
}

// Delete
func TestDelete(t *testing.T) {
   // DELETE FROM `user` WHERE uid=10
   _, err := g.DB().Model("user").Where("uid", 10000).Delete()
   if err != nil {
      panic(err)
   }
}

// Select Where
func TestWhere(t *testing.T) {
   // INSERT INTO `user`(`name`) VALUES('john')
   g.DB().Model("user").Data(g.Map{"uid": 10001, "name": "john"}).Insert()
   g.DB().Model("user").Data(g.Map{"uid": 10002, "name": "john2"}).Insert()
   // 數量
   count, err := g.DB().Model("user").Where("uid", 10001).Count()
   if err != nil {
      panic(err)
   }
   fmt.Println("count:", count)
   // 獲取單個值
   v, err := g.DB().Model("user").Where("uid", 10001).Fields("name").Value()
   if err != nil {
      panic(err)
   }
   fmt.Println("name:", v.String())
   // 查詢對象
   r, err := g.DB().Model("user").Where("uid", 10002).One()
   if err != nil {
      panic(err)
   }
   fmt.Println("name:", r.Map()["name"])
   // 查詢對象
   //l, err := g.DB().Table("user").As("t").Where("t.uid > ?", 10000).All()
   // 也可以簡寫爲 select * from user as t where t.uid > 10000
   l, err := g.DB().Model("user").As("t").All("t.uid > ?", 10000)
   if err != nil {
      panic(err)
   }
   for index, value := range l {
      fmt.Println(index, value["uid"], value["name"])
   }
   g.DB().Model("user").Where("uid", 10001).Delete()
   g.DB().Model("user").Where("uid", 10002).Delete()
}

代碼地址

項目視頻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章