Gorm分頁新方案,你學(xué)會(huì)了嗎?
Gorm是Go語言中最常用的ORM(對(duì)象關(guān)系映射)包之一,但它在某些功能上仍有不足,其中之一就是分頁。分頁是管理Web應(yīng)用程序中大數(shù)據(jù)集的基本功能。通過分頁,可以限制和顯示數(shù)據(jù)庫中的部分?jǐn)?shù)據(jù),而不必一次性檢索整個(gè)表的數(shù)據(jù)。
雖然Gorm的文檔中介紹了如何使用Scopes來實(shí)現(xiàn)分頁,但在靈活性和可用性上仍有改進(jìn)空間。本文介紹了一種利用Gorm的Clauses特性來簡化分頁并擴(kuò)展其功能的優(yōu)雅替代方案。
使用Gorm的Scopes進(jìn)行分頁
Gorm的文檔中將Scopes介紹為重用常用代碼的方法。在文檔示例中,我們可以看到定義了一個(gè)類似于以下的分頁Scope函數(shù):
func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
return func (db *gorm.DB) *gorm.DB {
// validate page and pageSize
...
offset := (page - 1) * pageSize
return db.Offset(offset).Limit(pageSize)
}
}
page := 0
pageSize := 10
db.Scopes(Paginate(page, pageSize)).Find(&users)
因此,為了應(yīng)用分頁,我們需要使用代碼db.Scopes(Paginate(page, pageSize))。
使用Clauses進(jìn)行分頁
另一種更為優(yōu)雅的方法是使用Gorm的Clauses。這種方法與使用Scopes略有不同,因?yàn)镃lauses負(fù)責(zé)修改數(shù)據(jù)庫查詢,特別是WHERE子句。
首先定義分頁結(jié)構(gòu)體:
type Pagination struct {
page int
pageSize int
}
func (p *Pagination) GetPage() int { return p.page }
func (p *Pagination) GetPageSize() int { return p.pageSize }
然后,實(shí)現(xiàn)使用該結(jié)構(gòu)體的gorm子句函數(shù)所需的兩個(gè)接口:
func (p *Pagination) ModifyStatement(stm *gorm.Statement) {
// 修改語句以添加分頁
db := stm.DB
stm.DB.Limit(p.pageSize).Offset((p.page - 1) * p.pageSize)
}
func (p *Pagination) Build(_ clause.Builder) {
// Build方法留空,因?yàn)榉猪摬恍枰~外的SQL子句
}
之后,可以按如下方式使用分頁:
pagination := Pagination{
page: 0,
pageSize: 10,
}
db.Clauses(&pagination).Find(&users)
為了使這種方法可重用并增強(qiáng)其功能,我開發(fā)了Pagorminator——一個(gè)簡化Gorm分頁并添加高級(jí)功能的庫,例如未分頁請(qǐng)求和自動(dòng)元數(shù)據(jù)填充(如總頁數(shù)和總計(jì)數(shù))。使用方法如下:
// 添加插件
_ = db.Use(pagorminator.PaGormMinator{})
pageRequest, _ := pagorminator.PageRequest(0, 10)
db.Clauses(pageRequest).Find(&users)
// 這將應(yīng)用分頁,并填充pageRequest,包括:
// - 總頁數(shù)
// - 總計(jì)數(shù)
分頁是數(shù)據(jù)庫驅(qū)動(dòng)應(yīng)用程序的關(guān)鍵功能。通過利用Clauses和類似Pagorminator的工具,可以在Gorm中實(shí)現(xiàn)強(qiáng)大且可重用的分頁功能。