Go使用XORM操作MySQL的陷阱盤點(diǎn)分析
使用 XORM 操作 MySQL 的陷阱
雖然使用 ORM 操作 MySQL 比直接使用標(biāo)準(zhǔn)庫(kù) `sql`[1] 和三方 MySQL 數(shù)據(jù)庫(kù)驅(qū)動(dòng)包[2]操作 MySQL 更加方便,但是也會(huì)遇到一些陷阱。
類型零值
在 Golang 中,每個(gè)數(shù)據(jù)類型都有各自的類型零值,比如 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 的類型零值,XORM 的 Update 方法會(huì)自動(dòng)忽略類型零值,所以該數(shù)據(jù) view 字段的值沒有更改。
但是,在實(shí)際項(xiàng)目開發(fā)中,我們可能需要將某個(gè)字段的值更新為該字段類型的類型零值,此時(shí)我們?cè)撛趺床僮髂兀?/p>
affected, err := engine.Cols("title", "view").Update(example, condi)
我們可以使用 Cols() 方法,指定需要更新的字段,這樣即便需要更新字段的值是該字段類型的類型零值,也可以正常更改。
提示:建議在設(shè)計(jì)數(shù)據(jù)庫(kù)表時(shí),字段的值盡量使用非類型零值。
自增 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ì)接著使用查詢方法,查詢最新一條數(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í)寫入當(dāng)前時(shí)間,此后將不再會(huì)更改;使用 xorm:updated 標(biāo)簽的字段,在第一次插入數(shù)據(jù)時(shí)寫入當(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)簽的字段的值沒被更改。
我們換一種更新數(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 可以滿足我們的需求。
總結(jié)
本文我們介紹了使用 XORM 操作 MySQL 時(shí),新手讀者朋友們可能會(huì)遇到的陷阱,希望可以給大家?guī)硪恍椭?,更多關(guān)于Go XORM操作MySQL的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go語(yǔ)言操作Excel利器之excelize類庫(kù)詳解
Excelize是Go語(yǔ)言編寫的用于操作Office Excel文檔基礎(chǔ)庫(kù),基于ECMA-376,ISO/IEC 29500國(guó)際標(biāo)準(zhǔn),可以使用它來讀取、寫入由Excel 2007及以上版本創(chuàng)建的電子表格文檔,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言操作Excel利器之excelize類庫(kù)的相關(guān)資料,需要的朋友可以參考下2022-10-10
Go語(yǔ)言展現(xiàn)快速排序算法全過程的思路及代碼示例
這篇文章主要介紹了Go語(yǔ)言展現(xiàn)快速排序算法全過程的思路及代碼示例,文章最后作者還提到了對(duì)Quick Sort算法優(yōu)化的一些想法,需要的朋友可以參考下2016-04-04
Go語(yǔ)言學(xué)習(xí)之運(yùn)算符使用詳解
這篇文章主要介紹了Go語(yǔ)言中常用運(yùn)算符的使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
go mutex互斥鎖使用Lock和Unlock方法占有釋放資源
Go號(hào)稱是為了高并發(fā)而生的,在高并發(fā)場(chǎng)景下,勢(shì)必會(huì)涉及到對(duì)公共資源的競(jìng)爭(zhēng),當(dāng)對(duì)應(yīng)場(chǎng)景發(fā)生時(shí),我們經(jīng)常會(huì)使用 mutex 的 Lock() 和 Unlock() 方法來占有或釋放資源,雖然調(diào)用簡(jiǎn)單,但 mutex 的內(nèi)部卻涉及挺多的,本文來好好研究一下2023-09-09
Golang中漏洞數(shù)據(jù)庫(kù)的使用詳解
govulncheck是Golang中的漏洞掃描工具,它強(qiáng)大功能的背后,離不開?Go?漏洞數(shù)據(jù)庫(kù)(Go?vulnerability?database)的支持,所以本文就來為大家詳細(xì)講解下?Go?漏洞數(shù)據(jù)庫(kù)相關(guān)的知識(shí)2023-09-09
Go錯(cuò)誤處理之panic函數(shù)和recover函數(shù)使用及捕獲異常方法
這篇文章主要介紹了Go錯(cuò)誤處理之panic函數(shù)使用及捕獲,本篇探討了如何使用 panic 和 recover 來處理 Go 語(yǔ)言中的異常,需要的朋友可以參考下2023-03-03

