ORM鏈?zhǔn)讲僮鞯淖侄芜^(guò)濾&為什么GoFrame不支持migrate功能?
初學(xué)者必須搞懂:
在 Go 中,沒(méi)有null、none、NULL、None
任何類(lèi)型在未初始化時(shí)都對(duì)應(yīng)一個(gè)零值:布爾類(lèi)型是 false ,整型是 0 ,字符串是 ""
而指針,函數(shù),interface,slice,channel和map的零值都是 nil
結(jié)合場(chǎng)景,平衡利弊,做出取舍
下圖是一位讀者問(wèn)我的問(wèn)題,我翻遍了文檔也沒(méi)找到相關(guān)的資料,猜測(cè)應(yīng)該是不支持的。
于是問(wèn)了goframe作者,被明確告知:goframe不支持,并且以后也不會(huì)支持。
作者也詳細(xì)解答了不支持的原因,goframe作者團(tuán)隊(duì)的考慮是這樣的:
因?yàn)槲易龅捻?xiàng)目比較多,在數(shù)據(jù)庫(kù)表結(jié)構(gòu)管理方面踩過(guò)坑。還是比較能接受goframe作者觀點(diǎn)的。
migrate這種功能確實(shí)能方便開(kāi)發(fā)者,但是在企業(yè)級(jí)項(xiàng)目中,尤其是TOB的業(yè)務(wù),穩(wěn)定是第一要?jiǎng)?wù)。migrate功能雖然方便,但是不夠嚴(yán)謹(jǐn),如果沒(méi)有很強(qiáng)的規(guī)范去約束團(tuán)隊(duì)成員的使用,很容易出問(wèn)題,出了問(wèn)題就不是小問(wèn)題,所以不敢用。
這也讓我想起了另外一件事情:
前段時(shí)間在review代碼時(shí),發(fā)現(xiàn)了一個(gè)“無(wú)條件”的刪除腳本在運(yùn)行,心頭一驚??!這要是把數(shù)據(jù)刪了可麻煩了。但是查詢(xún)DB發(fā)現(xiàn)沒(méi)有刪除數(shù)據(jù)。
我詳細(xì)查了官方文檔,沒(méi)有被刪數(shù)據(jù)的原因是這樣的:
goframe是一款用于企業(yè)生產(chǎn)級(jí)別的框架,各個(gè)模塊設(shè)計(jì)嚴(yán)謹(jǐn),工程實(shí)踐的細(xì)節(jié)處理得比較好。為安全性保證、防止誤操作,Update及Delete方法必須帶有Where條件才能提交執(zhí)行,否則將會(huì)錯(cuò)誤返回,錯(cuò)誤信息如:there should be WHERE condition statement for XXX operation。
好吧,感謝,真是救我狗命了,哈哈。
也正是因?yàn)樽约鹤隽撕芏囗?xiàng)目,踩了很多坑,碰到了不少這種細(xì)節(jié)問(wèn)題。
目前才有了“從追求開(kāi)發(fā)效率”到“追求項(xiàng)目穩(wěn)定性”的轉(zhuǎn)變。
在這里也回答一下最近大家私信我的問(wèn)題吧:“為什么我使用goframe框架做這個(gè)電商實(shí)戰(zhàn)項(xiàng)目?”
原因很簡(jiǎn)單,我結(jié)合自己的經(jīng)歷,覺(jué)得GoFrame是一個(gè)適合企業(yè)級(jí)項(xiàng)目比較嚴(yán)謹(jǐn)?shù)目蚣?,能少踩坑,避免一些麻煩。雖然入門(mén)門(mén)檻是有的,但是在“工程化開(kāi)發(fā)設(shè)計(jì)”的規(guī)范下,后續(xù)的維護(hù)成本還是比較低的。所以才帶大家使用這個(gè)框架做電商項(xiàng)目的。
好了,不同的場(chǎng)景,不同的項(xiàng)目有不同的解決方案,不同的優(yōu)選框架。這個(gè)問(wèn)題沒(méi)有標(biāo)準(zhǔn)答案,結(jié)合自己的需求去選擇合適的解決方案吧。
歡迎大家找我交流,多提像這位讀者一樣有價(jià)值的問(wèn)題,一起進(jìn)步!
Fields/FieldsEx字段過(guò)濾
Fields 用于指定需要操作的表字段,包括查詢(xún)字段、寫(xiě)入字段、更新字段等過(guò)濾;
FieldsEx 用于例外的字段指定,可用于查詢(xún)字段、寫(xiě)入字段、更新字段等過(guò)濾;
?Fields??示例
假如user?表有4個(gè)字段uid?, nickname?, passport?, password。
查詢(xún)字段過(guò)濾
寫(xiě)入字段過(guò)濾
?FieldsEx??示例
1.假如user?表有4個(gè)字段uid?, nickname?, passport?, password。
2.查詢(xún)字段排除
3.寫(xiě)入字段排除
OmitEmpty空值過(guò)濾
當(dāng) map/struct? 中存在空值如 nil,"",0? 時(shí),默認(rèn)情況下,gdb?將會(huì)將其當(dāng)做正常的輸入?yún)?shù),因此這些參數(shù)也會(huì)被更新到數(shù)據(jù)表。OmitEmpty特性可以在將數(shù)據(jù)寫(xiě)入到數(shù)據(jù)庫(kù)之前過(guò)濾空值數(shù)據(jù)的字段。
相關(guān)方法:
OmitEmpty?方法會(huì)同時(shí)過(guò)濾Where及Data?中的空值數(shù)據(jù),而通過(guò)OmitEmptyWhere/OmitEmptyData方法可以執(zhí)行特定的字段過(guò)濾。
寫(xiě)入/更新操作
空值會(huì)影響于寫(xiě)入/更新操作方法,如Insert?, Replace?, Update?, Save?操作。如以下操作(以map?為例,struct同理):
針對(duì)空值情況,我們可以通過(guò)OmitEmpty方法來(lái)過(guò)濾掉這些空值。例如,以上示例可以修改為:
對(duì)于struct數(shù)據(jù)參數(shù),我們也可以進(jìn)行空值過(guò)濾。操作示例:
注意喲,批量寫(xiě)入/更新操作中OmitEmpty方法將會(huì)失效,因?yàn)樵谂坎僮髦?,必須保證每個(gè)寫(xiě)入記錄的字段是統(tǒng)一的。
關(guān)于omitempty?標(biāo)簽與OmitEmpty方法:
針對(duì)于struct?的空值過(guò)濾大家會(huì)想到omitempty?的標(biāo)簽。該標(biāo)簽常用于json?轉(zhuǎn)換的空值過(guò)濾,也在某一些第三方的ORM?庫(kù)中用作struct到數(shù)據(jù)表字段的空值過(guò)濾,即當(dāng)屬性為空值時(shí)不做轉(zhuǎn)換。
omitempty?標(biāo)簽與OmitEmpty?方法所達(dá)到的效果是一樣的。在ORM?操作中,我們不建議對(duì)struct?使用omitempty?的標(biāo)簽來(lái)控制字段的空值過(guò)濾,而建議使用OmitEmpty?方法來(lái)做控制。因?yàn)樵摌?biāo)簽一旦加上之后便綁定到了struct?上,沒(méi)有辦法做靈活控制;而通過(guò)OmitEmpty?方法使得開(kāi)發(fā)者可以選擇性地、根據(jù)業(yè)務(wù)場(chǎng)景對(duì)struct做空值過(guò)濾,操作更加靈活。
數(shù)據(jù)查詢(xún)操作
空值也會(huì)影響數(shù)據(jù)查詢(xún)操作,主要是影響where?條件參數(shù)。我們可以通過(guò)OmitEmpty方法過(guò)濾條件參數(shù)中的空值。
使用示例:
OmitNil空值過(guò)濾
當(dāng) map/struct? 中存在空值如 nil?時(shí),默認(rèn)情況下,gdb?將會(huì)將其當(dāng)做正常的輸入?yún)?shù),因此這些參數(shù)也會(huì)被更新到數(shù)據(jù)表。OmitNil?特性可以在將數(shù)據(jù)寫(xiě)入到數(shù)據(jù)庫(kù)之前過(guò)濾空值數(shù)據(jù)的字段。與OmitEmpty?特性的區(qū)別在于,OmitNil?只會(huì)過(guò)濾值為nil?的空值字段,其他空值如"",0并不會(huì)被過(guò)濾。
相關(guān)方法:
OmitNil?方法會(huì)同時(shí)過(guò)濾Where及Data?中的空值數(shù)據(jù),而通過(guò)OmitNilWhere/OmitNilData方法可以執(zhí)行特定的字段過(guò)濾。
Filter字段過(guò)濾(已內(nèi)置)
gdb?可以自動(dòng)同步數(shù)據(jù)表結(jié)構(gòu)到程序緩存中(緩存不過(guò)期,直至程序重啟/重新部署),并且可以過(guò)濾提交參數(shù)中不符合表結(jié)構(gòu)的數(shù)據(jù)項(xiàng),該特性可以使用Filter?方法實(shí)現(xiàn)。常用于新增/刪除操作中輸入map/struct/[]map/[]string參數(shù)類(lèi)型的場(chǎng)景。
使用示例,假如user?表有4個(gè)字段uid?, nickname?, passport?, password:
其中id為不存在的字段,在寫(xiě)入數(shù)據(jù)時(shí)將會(huì)被過(guò)濾掉,不至于被構(gòu)造成寫(xiě)入SQL中產(chǎn)生執(zhí)行錯(cuò)誤。
數(shù)據(jù)庫(kù)沒(méi)有設(shè)計(jì)為Data?方法做自動(dòng)過(guò)濾,而是需要開(kāi)發(fā)者調(diào)用Filter方法來(lái)手動(dòng)指定過(guò)濾,目的是友好地提醒開(kāi)發(fā)者可能誤寫(xiě)/傳遞錯(cuò)誤了字段名稱(chēng)。如果強(qiáng)制性的自動(dòng)過(guò)濾可能會(huì)引起難以預(yù)料的業(yè)務(wù)邏輯異常,例如,由于字段名稱(chēng)拼寫(xiě)錯(cuò)誤導(dǎo)致自動(dòng)過(guò)濾了本來(lái)需要輸入的字段,導(dǎo)致寫(xiě)入數(shù)據(jù)庫(kù)的數(shù)據(jù)不完整。
從GoFrame v1.15.7?版本開(kāi)始,根據(jù)社區(qū)整體反饋,為提高組件易用性,filter?特性被設(shè)置為默認(rèn)開(kāi)啟,不再需要顯示調(diào)用,F(xiàn)ilter方法已被標(biāo)記廢棄。
本文轉(zhuǎn)載自微信公眾號(hào)「 程序員升級(jí)打怪之旅」,作者「王中陽(yáng)Go」,可以通過(guò)以下二維碼關(guān)注。
轉(zhuǎn)載本文請(qǐng)聯(lián)系「 程序員升級(jí)打怪之旅」公眾號(hào)。