GoFrame 鏈式操作-模型創(chuàng)建

2022-04-01 16:14 更新

模型創(chuàng)建

Model

?Model?方法用于創(chuàng)建基于數(shù)據(jù)表的?Model?對象。常見的,也可以使用?g?對象管理模塊中的?Model?方法在默認的數(shù)據(jù)庫配置上創(chuàng)建?Model?對象。

使用示例:

g.Model("user")
// 或者或者
g.DB().Model("user")

此外,在某些場景下,我們也可以通過?DB?方法切換當前模型的數(shù)據(jù)庫對象,例如:

m := g.Model("user")
m  = m.DB(g.DB("user-center"))

其效果與以下操作是一樣的:

m := g.DB("user-center").Model("user")

Raw

?Raw?方法用于創(chuàng)建一個基于原始?SQL?語句的?Model?對象。也可以使用?g?對象管理模塊中的?ModelRaw?方法通過給定的?SQL?語句在默認的數(shù)據(jù)庫配置上創(chuàng)建?Model?對象。

s := "SELECT * FROM `user` WHERE `status` IN(?)"
m := g.ModelRaw(s, g.Slice{1,2,3}).WhereLT("age", 18).Limit(10).OrderAsc("id").All()
// SELECT * FROM `user` WHERE `status` IN(1,2,3) AND `age`<18 ORDER BY `id` ASC LIMIT 10

鏈式安全

鏈式安全只是模型操作的兩種方式區(qū)別:一種會修改當前?model?對象(不安全,默認),一種不會(安全)但是模型屬性修改/條件疊加需要使用賦值操作,僅此而已。

默認情況

在默認情況下,?gdb?是非鏈式安全的,也就是說鏈式操作的每一個方法都將對當前操作的?Model?屬性進行修改,因此該?Model?對象不可以重復(fù)使用。例如,當存在多個分開查詢的條件時,我們可以這么來使用?Model?對象:

user := g.Model("user")
user.Where("status IN(?)", g.Slice{1,2,3})
if vip {
    // 查詢條件自動疊加,修改當前模型對象
    user.Where("money>=?", 1000000)
} else {
    // 查詢條件自動疊加,修改當前模型對象
    user.Where("money<?",  1000000)
}
//  vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < 1000000
r, err := user.All()
//  vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < 1000000
n, err := user.Count()

可以看到,如果是分開執(zhí)行鏈式操作,鏈式的每一個操作都會修改已有的?Model?對象,查詢條件會自動疊加,因此?user?對象不可重復(fù)使用,否則條件會不停疊加。并且在這種使用方式中,每次我們需要操作?user?用戶表,都得使用?g.DB().Table("user")?這樣的語法創(chuàng)建一個新的?user?模型對象,相對來說會比較繁瑣。

默認情況下,基于性能以及?GC?優(yōu)化考慮,模型對象為非鏈式安全,防止產(chǎn)生過多的臨時模型對象。

Clone方法

此外,我們也可以手動調(diào)動?Clone?方法克隆當前模型,創(chuàng)建一個新的模型來實現(xiàn)鏈式安全,由于是新的模型對象,因此并不擔(dān)心會修改已有的模型對象的問題。例如:

// 定義一個用戶模型單例
user := g.Model("user")
// 克隆一個新的用戶模型
m := user.Clone()
m.Where("status IN(?)", g.Slice{1,2,3})
if vip {
    m.And("money>=?", 1000000)
} else {
    m.And("money<?",  1000000)
}
//  vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < 1000000
r, err := m.All()
//  vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < 1000000
n, err := m.Count()

Safe方法

當然,我們可以通過?Safe?方法設(shè)置當前模型為鏈式安全的對象,后續(xù)的每一個鏈式操作都將返回一個新的?Model?對象,該?Model?對象可重復(fù)使用。但需要特別注意的是,模型屬性的修改,或者操作條件的疊加,需要通過變量賦值的方式(?m = m.xxx?)覆蓋原有的模型對象來實現(xiàn)。例如:

// 定義一個用戶模型單例
user := g.Model("user").Safe()
m := user.Where("status IN(?)", g.Slice{1,2,3})
if vip {
    // 查詢條件通過賦值疊加
    m = m.And("money>=?", 1000000)
} else {
    // 查詢條件通過賦值疊加
    m = m.And("money<?",  1000000)
}
//  vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < 1000000
r, err := m.All()
//  vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < 1000000
n, err := m.Count()

可以看到,示例中的用戶模型單例對象?user?可以重復(fù)使用,而不用擔(dān)心被“污染”的問題。在這種鏈式安全的方式下,我們可以創(chuàng)建一個用戶單例對象?user?,并且可以重復(fù)使用到后續(xù)的各種查詢中。但是存在多個查詢條件時,條件的疊加需要通過模型賦值操作(?m = m.xxx?)來實現(xiàn)。

使用?Safe?方法標記之后,每一個鏈式操作都將會創(chuàng)建一個新的臨時模型對象(內(nèi)部自動使用?Clone?實現(xiàn)模型克?。?,從而實現(xiàn)鏈式安全。這種使用方式在模型操作中比較常見。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號