golang xorm mysql_golang-xorm库快速学习
xorm
xorm是一個Go語言ORM庫. 通過它可以使數據庫操作非常簡便.
全部文檔點我
用法入門:
前提:定義本文中用到的struct和基本代碼如下//?銀行賬戶type?Account?struct?{
Id??????int64
Name????string?`xorm:"unique"`
Balance?float64
Version?int?`xorm:"version"`?//?樂觀鎖}
var?x?*xorm.Engine創建orm引擎
注意:若想配合mysql,需要提前加載mysql驅動,通過如此方式
import _ "github.com/go-sql-driver/mysql"
x,err:=xorm.NewEngine("mysql", "root:111111@/sys?charset=utf8")自動同步表結構if?err?=?x.Sync2(new(Account));?err?!=?nil?{????????log.Fatalf("Fail?to?sync?database:?%v\n",?err)
}
Sync2會進行如下這些操作:自動檢測和創建表,這個檢測是根據表的名字
自動檢測和新增表中的字段,這個檢測是根據字段名,同時對表中多余的字段給出警告信息
自動檢測,創建和刪除索引和唯一索引,這個檢測是根據索引的一個或多個字段名,而不根據索引名稱。因此這里需要注意,如果在一個有大量數據的表中引入新的索引,數據庫可能需要一定的時間來建立索引。
自動轉換varchar字段類型到text字段類型,自動警告其它字段類型在模型和數據庫之間不一致的情況。
自動警告字段的默認值,是否為空信息在模型和數據庫之間不匹配的情況
以上這些警告信息需要將engine.ShowWarn 設置為 true 才會顯示。增刪改操作
**增加操作:插入一條新的記錄,該記錄必須是未存在的,否則會返回錯誤:
**
_, err := x.Insert(&Account{Name: name, Balance: balance})
刪除操作:
_, err := x.Delete(&Account{Id: id})
方法 Delete 接受參數后,會自動根據傳進去的值進行查找,然后刪除。比如此處,我們指定了 Account 的 ID 字段,那么就會刪除 ID 字段值與我們所賦值相同的記錄;如果您只對 Name 字段賦值,那么 xorm 就會去查找 Name 字段值匹配的記錄。如果多個字段同時賦值,則是多個條件同時滿足的記錄才會被刪除。
刪除操作針對的對象沒有限制,凡是按照條件查找到的,都會被刪除(單個與批量刪除)。
獲取和修改記錄:想要修改的記錄必須是提前存在的,所以修改前要先查詢所要修改的記錄
獲取記錄:
Get方法
查詢單條數據使用Get方法,在調用Get方法時需要傳入一個對應結構體的指針,同時結構體中的非空field自動成為查詢的條件和前面的方法條件組合在一起查詢。
a. 根據Id來獲得單條數據:a:=&Account{}
has,?err?:=?x.Id(id).Get(a)
b. 根據where獲取單條數據a?:=?new(Account)
has,?err?:=?x.Where("name=?",?"adn").Get(a)
c. 根據Account結構體中存在的非空數據來獲取單條數據a?:=?&Account{Id:1}
has,?err?:=?x.Get(a)
返回的結果為兩個參數,一個has(bool類型)為該條記錄是否存在,第二個參數err為是否有錯誤。不管err是否為nil,has都有可能為true或者false。
在獲取到記錄之后,我們就需要進行一些修改,然后更新到數據庫:a.Balance?+=?deposit//?對已有記錄進行更新_,?err?=?x.Update(a)
注意,Update接受的參數是指針
批量獲取信息
err = x.Desc("balance").Find(&as)
在這里,我們還調用了 Desc 方法對記錄按照存款數額將賬戶從大到小排序。
Find方法的第一個參數為slice的指針或Map指針,即為查詢后返回的結果,第二個參數可選,為查詢的條件struct的指針。樂觀鎖
樂觀鎖是 xorm 提供的一個比較實用的功能,通過在 tag 中指定 version 來開啟它。開啟之后,每次對記錄進行更新的時候,該字段的值就會自動遞增 1。如此一來,您就可以判斷是否有其它地方同時修改了該記錄,如果是,則應當重新操作,否則會出現錯誤的數據(同時對一個帳號進行取款操作卻只扣了一次的數額)。
事務及回滾
廢話不多說,直接上示例代碼://?創建?Session?對象sess?:=?x.NewSession()
defer?sess.Close()//?開啟事務if?err?=?sess.Begin();?err?!=?nil?{????return?err
}if?_,?err?=?sess.Update(a1);?err?!=?nil?{????//?發生錯誤時進行回滾
sess.Rollback()????return?err
}
//?完成事務return?sess.Commit()
統計記錄條數- Count方法
統計數據使用Count方法,Count方法的參數為struct的指針并且成為查詢條件。a?:=?new(Account)//返回滿足id>1的Account的記錄條數total,?err?:=?x.Where("id?>?",?1).Count(a)
//返回Account所有記錄條數
total,err?=?x.Count(a)
Iterate方法
Iterate方法提供逐條執行查詢到的記錄的方法,他所能使用的條件和Find方法完全相同err?:=?x.Where("id?>??=)",?30).Iterate(new(Account),?func(i?int,?bean?interface{})error{
user?:=?bean.(*Account)????//do?somthing?use?i?and?user})
我們主要來看迭代函數的聲明:它接受 2 個參數,第一個是當前記錄所對應的索引(該索引和 ID 的值毫無關系,只是查詢后結果的索引),第二個參數則是保存了相關類型的空接口,需要自行斷言,例如示例中使用 bean.(*Account) 因為我們知道查詢的結構是 Account。
查詢特定字段
使用 Cols 方法可以指定查詢特定字段,當只有結構中的某個字段的值對您有價值時,就可以使用它:x.Cols("name").Iterate(new(Account),?printFn)
var?printFn?=?func(idx?int,?bean?interface{})?error?{????//dosomething
return?nil
}
此處,所查詢出來的結構只有 Name 字段有值,其它字段均為零值。要注意的是,Cols 方法所接受的參數是數據表中對應的名稱,而不是字段名稱。
排除特定字段
當您希望刻意忽略某個字段的查詢結果時,可以使用 Omit 方法:
x.Omit("name").Iterate(new(Account), printFn)
此處,所查詢出來的結構只有 Name 字段為零值。要注意的是,Omit 方法所接受的參數是數據表中對應的名稱,而不是字段名稱。
查詢結果偏移
查詢結果偏移在分頁應用中最為常見,通過 Limit 方法可以達到一樣的目的:x.Limit(3,?2).Iterate(new(Account),?printFn)
該方法最少接受 1 個參數,第一個參數表示取出的最大記錄數;如果傳入第二個參數,則表示對查詢結果進行偏移。因此,此處的查詢結果為偏移 2 個后,再最多取出 3 個記錄。
日志記錄
一般情況下,使用x.ShowSQL = true來開啟 xorm 最基本的日志功能,所有 SQL 都會被打印到控制臺,但如果您想要將日志保存到文件,則可以在獲取到 ORM 引擎之后,進行如下操作:f,?err?:=?os.Create("sql.log")if?err?!=?nil?{????log.Fatalf("Fail?to?create?log?file:?%v\n",?err)????return}
x.Logger?=?xorm.NewSimpleLogger(f)
LRU 緩存
作為唯一支持 LRU 緩存的一款 ORM,如果不知道如何使用這個特性,那將是非常遺憾。不過,想要使用它也并不困難,只需要在獲取到 ORM 引擎之后,進行如下操作:cacher?:=?xorm.NewLRUCacher(xorm.NewMemoryStore(),?1000)
x.SetDefaultCacher(cacher)
這樣就算是使用最基本的緩存功能了。該功能還支持只緩存某些表或排除緩存某些表,詳情可以參見 文章首部的官方文檔。
事件鉤子
官方一共提供了 6 類 事件鉤子,示例中只演示其中 2 種:BeforeInsert 和 AfterInsert。全部內容查看文章首部官方文檔
它們的作用分別會在 進行插入記錄之前 和 完成插入記錄之后 被調用:
func (a *Account) BeforeInsert() {
log.Printf("before insert: %s", a.Name)
}
func (a *Account) AfterInsert() {
log.Printf("after insert: %s", a.Name)
}
下面是一個簡單的銀行存取款的小例子package?main
import?(????"errors"
"log"
"github.com/go-xorm/xorm"
_?"github.com/mattn/go-sqlite3")//?銀行賬戶type?Account?struct?{
Id??????int64
Name????string?`xorm:"unique"`
Balance?float64
Version?int?`xorm:"version"`?//?樂觀鎖}//?ORM?引擎var?x?*xorm.Engine
func?init()?{????//?創建?ORM?引擎與數據庫
var?err?error
x,?err?=?xorm.NewEngine("mysql",?"root:111111@/sys?charset=utf8")????if?err?!=?nil?{
log.Fatalf("Fail?to?create?engine:?%v\n",?err)
}????//?同步結構體與數據表
if?err?=?x.Sync(new(Account));?err?!=?nil?{
log.Fatalf("Fail?to?sync?database:?%v\n",?err)
}
}//?創建新的賬戶func?newAccount(name?string,?balance?float64)?error?{????//?對未存在記錄進行插入
_,?err?:=?x.Insert(&Account{Name:?name,?Balance:?balance})????return?err
}//?獲取賬戶信息func?getAccount(id?int64)?(*Account,?error)?{
a?:=?&Account{}????//?直接操作?ID?的簡便方法
has,?err?:=?x.Id(id).Get(a)????//?判斷操作是否發生錯誤或對象是否存在
if?err?!=?nil?{????????return?nil,?err
}?else?if?!has?{????????return?nil,?errors.New("Account?does?not?exist")
}????return?a,?nil}//?用戶轉賬func?makeTransfer(id1,?id2?int64,?balance?float64)?error?{????//?創建?Session?對象
sess?:=?x.NewSession()
defer?sess.Close()????//?啟動事務
if?err?=?sess.Begin();?err?!=?nil?{????????return?err
}
a1,?err?:=?getAccount(id1)????if?err?!=?nil?{????????return?err
}
a2,?err?:=?getAccount(id2)????if?err?!=?nil?{????????return?err
}????if?a1.Balance?
}
a1.Balance?-=?balance
a2.Balance?+=?balance????if?_,?err?=?sess.Update(a1);?err?!=?nil?{????????//?發生錯誤時進行回滾
sess.Rollback()????????return?err
}????if?_,?err?=?sess.Update(a2);?err?!=?nil?{
sess.Rollback()????????return?err
}????//?完成事務
return?sess.Commit()????return?nil}//?用戶存款func?makeDeposit(id?int64,?deposit?float64)?(*Account,?error)?{
a,?err?:=?getAccount(id)????if?err?!=?nil?{????????return?nil,?err
}
sess?:=?x.NewSession()
defer?sess.Close()????if?err?=?sess.Begin();?err?!=?nil?{????????return?nil,?err
}
a.Balance?+=?deposit????//?對已有記錄進行更新
if?_,?err?=?sess.Update(a);?err?!=?nil?{
sess.Rollback()????????return?nil,?err
}????return?a,?sess.Commit()
}//?用戶取款func?makeWithdraw(id?int64,?withdraw?float64)?(*Account,?error)?{
a,?err?:=?getAccount(id)????if?err?!=?nil?{????????return?nil,?err
}????if?a.Balance?
}
sess?:=?x.NewSession()
defer?sess.Close()????if?_,?err?=?sess.Begin();?err?!=?nil?{????????return?nil,?err
}
a.Balance?-=?withdraw????if?_,?err?=?sess.Update(a);?err?!=?nil?{????????return?nil,?err
}????return?a,?sess.Commit()
}//?按照?ID?正序排序返回所有賬戶func?getAccountsAscId()?(as?[]Account,?err?error)?{????//?使用?Find?方法批量獲取記錄
err?=?x.Find(&as)????return?as,?err
}//?按照存款倒序排序返回所有賬戶func?getAccountsDescBalance()?(as?[]Account,?err?error)?{????//?使用?Desc?方法使結果呈倒序排序
err?=?x.Desc("balance").Find(&as)????return?as,?err
}//?刪除賬戶func?deleteAccount(id?int64)?error?{????//?通過?Delete?方法刪除記錄
_,?err?:=?x.Delete(&Account{Id:?id})????return?err
}
注:本文參考
作者:ifcoder
鏈接:https://www.jianshu.com/p/13d46e5d2d2a
總結
以上是生活随笔為你收集整理的golang xorm mysql_golang-xorm库快速学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云计算职业技能大赛(容器云运维)
- 下一篇: Redis 队列和MQ 对比