Go使用XORM操作MySQL的陷阱盤(pán)點(diǎn)分析
使用 XORM 操作 MySQL 的陷阱
雖然使用 ORM 操作 MySQL 比直接使用標(biāo)準(zhǔn)庫(kù) `sql`[1] 和三方 MySQL 數(shù)據(jù)庫(kù)驅(qū)動(dòng)包[2]操作 MySQL 更加方便,但是也會(huì)遇到一些陷阱。
類(lèi)型零值
在 Golang 中,每個(gè)數(shù)據(jù)類(lèi)型都有各自的類(lèi)型零值,比如 int 的零值是 0
,string 的零值是 ''
等。
示例代碼:
package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "xorm.io/xorm" ) func main() { // 創(chuàng)建 Engine engine, err := xorm.NewEngine("mysql", "root:root@/example?charset=utf8") defer func() { err = engine.Close() if err != nil { fmt.Printf("engine close err=%v\n", err) return } }() if err != nil { fmt.Printf("init xorm engine fail, err=%v\n", err) return } // 更新數(shù)據(jù) example := &Example{ Title: "go", View: 0, } condi := &Example{ Id: 2, } affected, err := engine.Update(example, condi) if err != nil { fmt.Printf("Update err=%v\n", err) return } fmt.Printf("affected=%d\n", affected) } type Example struct { Id int `json:"id" form:"id"` Title string `json:"title" form:"title"` View int `json:"view" form:"view"` Created int `json:"created" form:"created" xorm:"created"` Updated int `json:"updated" form:"updated" xorm:"updated"` }
閱讀上面這段代碼,我們可以發(fā)現(xiàn)示例代碼中將 id=2
的數(shù)據(jù) view 字段更新為 0
,因?yàn)?nbsp;0
是 int 的類(lèi)型零值,XORM 的 Update 方法會(huì)自動(dòng)忽略類(lèi)型零值,所以該數(shù)據(jù) view 字段的值沒(méi)有更改。
但是,在實(shí)際項(xiàng)目開(kāi)發(fā)中,我們可能需要將某個(gè)字段的值更新為該字段類(lèi)型的類(lèi)型零值,此時(shí)我們?cè)撛趺床僮髂兀?/p>
affected, err := engine.Cols("title", "view").Update(example, condi)
我們可以使用 Cols()
方法,指定需要更新的字段,這樣即便需要更新字段的值是該字段類(lèi)型的類(lèi)型零值,也可以正常更改。
提示:建議在設(shè)計(jì)數(shù)據(jù)庫(kù)表時(shí),字段的值盡量使用非類(lèi)型零值。
自增 id
在插入數(shù)據(jù)時(shí),我們可能需要返回自增 id,我們先看一段代碼:
// 插入數(shù)據(jù) example := &Example{ Title: "PHP", View: 90, } affected, err := engine.Insert(example) if err != nil { fmt.Printf("Insert err=%v\n", err) return } fmt.Printf("affected=%v\n", affected)
閱讀上面這段代碼,我們插入一條數(shù)據(jù),返回結(jié)果是影響行數(shù)和錯(cuò)誤信息,而不是直接返回該條數(shù)據(jù)的自增 id。
可能有些讀者朋友們會(huì)接著使用查詢(xún)方法,查詢(xún)最新一條數(shù)據(jù)的 id,在并發(fā)請(qǐng)求數(shù)低的場(chǎng)景中,該方法是可以查到新插入數(shù)據(jù)的自增 id。
但是在并發(fā)請(qǐng)求數(shù)高的場(chǎng)景中,該方法查到的最新一條數(shù)據(jù)的 id,未必是我們剛插入的數(shù)據(jù)的自增 id。
id := example.Id fmt.Printf("affected=%v || id=%d\n", affected, id)
閱讀上面這段代碼,我們想要獲取新插入數(shù)據(jù)的自增 id,直接 example.Id
即可獲取,但是前提條件是結(jié)構(gòu)體中,id
字段使用 xorm:"autoincr"
標(biāo)簽。
更新 created 字段
我們?cè)诮Y(jié)構(gòu)體中,使用標(biāo)簽 xorm:created
和 xorm:updated
即可自動(dòng)插入當(dāng)前時(shí)間。
但是,使用 xorm:created
標(biāo)簽的字段,只有在第一次插入數(shù)據(jù)時(shí)寫(xiě)入當(dāng)前時(shí)間,此后將不再會(huì)更改;使用 xorm:updated
標(biāo)簽的字段,在第一次插入數(shù)據(jù)時(shí)寫(xiě)入當(dāng)前時(shí)間,此后每次 Update 操作,時(shí)間都會(huì)更改。
如果我們的業(yè)務(wù)需求是需要更改使用 xorm:created
標(biāo)簽的字段,可以做到嗎?
// 更改數(shù)據(jù) example := &Example{ Title: "JavaScript", View: 98, } condi := &Example{ Id: 2, } affected, err := engine.Update(example, condi) if err != nil { fmt.Printf("Update err=%v\n", err) return } fmt.Printf("affected=%d\n", affected)
閱讀上面這段代碼,我們發(fā)現(xiàn)執(zhí)行 Update 方法之后,使用 xorm:updated
標(biāo)簽的字段的值被更改,而使用 xorm:created
標(biāo)簽的字段的值沒(méi)被更改。
我們換一種更新數(shù)據(jù)的方式,代碼如下:
// 更改數(shù)據(jù) sql := "UPDATE example SET title=?, view=?, created=? WHERE id=?" res, err := engine.Exec(sql, "Python", 60, time.Now().Unix(), 2) if err != nil { fmt.Printf("Update err=%v\n", err) return } affected, err := res.RowsAffected() if err != nil { fmt.Printf("RowsAffected err=%v\n", err) return } fmt.Printf("affected=%d\n", affected)
閱讀上面這段代碼,我們可以發(fā)現(xiàn)使用 Exec 方法執(zhí)行原生 SQL 可以滿(mǎn)足我們的需求。
總結(jié)
本文我們介紹了使用 XORM 操作 MySQL 時(shí),新手讀者朋友們可能會(huì)遇到的陷阱,希望可以給大家?guī)?lái)一些幫助,更多關(guān)于Go XORM操作MySQL的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Go語(yǔ)言中獲取文件路徑的不同方法與應(yīng)用場(chǎng)景
在使用?Go?開(kāi)發(fā)項(xiàng)目時(shí),估計(jì)有不少人遇到過(guò)無(wú)法正確處理文件路徑的問(wèn)題,本文將嘗試從簡(jiǎn)單到復(fù)雜,詳細(xì)介紹?Go?中獲取路徑的不同方法及應(yīng)用場(chǎng)景,希望對(duì)大家有所幫助2024-02-02go?zero微服務(wù)實(shí)戰(zhàn)處理每秒上萬(wàn)次的下單請(qǐng)求
這篇文章主要為大家介紹了go?zero微服務(wù)實(shí)戰(zhàn)處理每秒上萬(wàn)次的下單請(qǐng)求示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Go語(yǔ)言利用time.After實(shí)現(xiàn)超時(shí)控制的方法詳解
最近在學(xué)習(xí)golang,所以下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言利用time.After實(shí)現(xiàn)超時(shí)控制的相關(guān)資料,文中通過(guò)示例介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08Golang 實(shí)現(xiàn)Thrift客戶(hù)端連接池方式
這篇文章主要介紹了Golang 實(shí)現(xiàn)Thrift客戶(hù)端連接池方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12使用Go語(yǔ)言編寫(xiě)一個(gè)極簡(jiǎn)版的容器Container
Docker作為一種流行的容器化技術(shù),對(duì)于每一個(gè)程序開(kāi)發(fā)者而言都具有重要性和必要性,因?yàn)槿萜骰嚓P(guān)技術(shù)的普及大大簡(jiǎn)化了開(kāi)發(fā)環(huán)境配置、更好的隔離性和更高的安全性,對(duì)于部署項(xiàng)目和團(tuán)隊(duì)協(xié)作而言也更加方便,本文將嘗試使用Go語(yǔ)言編寫(xiě)一個(gè)極簡(jiǎn)版的容器2023-10-10淺談golang fasthttp踩坑經(jīng)驗(yàn)
本文主要介紹了golang fasthttp踩坑經(jīng)驗(yàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Golang對(duì)struct字段重新排序優(yōu)化數(shù)據(jù)結(jié)構(gòu)性能實(shí)踐
這篇文章主要為大家介紹了Golang對(duì)struct字段重新排序優(yōu)化數(shù)據(jù)結(jié)構(gòu)性能實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12