GORM分页新方案

科技   2024-12-02 09:45   广东  

Gorm是Go语言中最常用的ORM(对象关系映射)包之一,但它在某些功能上仍有不足,其中之一就是分页。分页是管理Web应用程序中大数据集的基本功能。通过分页,可以限制和显示数据库中的部分数据,而不必一次性检索整个表的数据。

虽然Gorm的文档中介绍了如何使用Scopes来实现分页,但在灵活性和可用性上仍有改进空间。本文介绍了一种利用Gorm的Clauses特性来简化分页并扩展其功能的优雅替代方案。

使用Gorm的Scopes进行分页

Gorm的文档中将Scopes介绍为重用常用代码的方法。在文档示例中,我们可以看到定义了一个类似于以下的分页Scope函数:

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)

因此,为了应用分页,我们需要使用代码db.Scopes(Paginate(page, pageSize))

使用Clauses进行分页

另一种更为优雅的方法是使用Gorm的Clauses。这种方法与使用Scopes略有不同,因为Clauses负责修改数据库查询,特别是WHERE子句。

首先定义分页结构体:

type Pagination struct {
  page     int
  pageSize int
}

func (p *Pagination) GetPage() int { return p.page }
func (p *Pagination) GetPageSize() int { return p.pageSize }

然后,实现使用该结构体的gorm子句函数所需的两个接口:

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方法留空,因为分页不需要额外的SQL子句
}

之后,可以按如下方式使用分页:

pagination := Pagination{
  page: 0,
  pageSize: 10,
}
db.Clauses(&pagination).Find(&users)

为了使这种方法可重用并增强其功能,我开发了Pagorminator——一个简化Gorm分页并添加高级功能的库,例如未分页请求和自动元数据填充(如总页数和总计数)。使用方法如下:

// 添加插件
_ = db.Use(pagorminator.PaGormMinator{})

pageRequest, _ := pagorminator.PageRequest(010)
db.Clauses(pageRequest).Find(&users)
// 这将应用分页,并填充pageRequest,包括:
// - 总页数
// - 总计数

分页是数据库驱动应用程序的关键功能。通过利用Clauses和类似Pagorminator的工具,可以在Gorm中实现强大且可重用的分页功能。希望您能尝试一下,并分享您的想法!

点击关注并扫码添加进交流群
免费领取「Go 语言」学习资料

源自开发者
专注于提供关于Go语言的实用教程、案例分析、最新趋势,以及云原生技术的深度解析和实践经验分享。
 最新文章