美文网首页
Gorm scope实现分页

Gorm scope实现分页

作者: Go语言由浅入深 | 来源:发表于2022-05-24 22:33 被阅读0次

    Gorm是一个非常棒的ORM。今天,我将向您展示如何使用Gorm Scopes创建分页。

    Scopes可以实现一些逻辑的复用,这些逻辑需要定义为如下格式:

    func(*gorm.DB) *gorm.DB 
    

    首先创建一个Pagination结构体:

    type Pagination struct {
        PageSize   int         `json:"pageSize,omitempty" form:"pageSize"`
        PageIndex  int         `json:"pageIndex,omitempty" form:"pageIndex"`
        Sort       string      `json:"sort,omitempty" form:"sort"`
        TotalRows  int64       `json:"total_rows"`
        TotalPages int         `json:"total_pages"`
        Rows       interface{} `json:"rows"`
    }
    
    func (p *Pagination) GetOffset() int {
        return (p.GetPage() - 1) * p.GetLimit()
    }
    
    func (p *Pagination) GetLimit() int {
        if p.PageSize == 0 {
            p.PageSize = 10
        }
        return p.PageSize
    }
    
    func (p *Pagination) GetPage() int {
        if p.PageIndex == 0 {
            p.PageIndex = 1
        }
        return p.PageIndex
    }
    
    func (p *Pagination) GetSort() string {
        if p.Sort == "" {
            p.Sort = "Id desc"
        }
        return p.Sort
    }
    

    然后创建Gorm Scope。

    func paginate(value interface{}, pagination *pkg.Pagination, db *gorm.DB) func(db *gorm.DB) *gorm.DB {  
        var totalRows int64 
        db.Model(value).Count(&totalRows)   
     
        pagination.TotalRows = totalRows    
        totalPages := int(math.Ceil(float64(totalRows) / float64(pagination.Limit)))    
        pagination.TotalPages = totalPages  
     
        return func(db *gorm.DB) *gorm.DB { 
            return db.Offset(pagination.GetOffset()).Limit(pagination.GetLimit()).Order(pagination.GetSort())   
        }   
    }
    

    然后将Gorm scope用在你的代码中使用,如下所示:

    package pagination
    
    import (
        "log"
        "math"
    
        "awesomeProject/pkg"
    
        "github.com/gin-gonic/gin"
        "gorm.io/driver/sqlite"
        "gorm.io/gorm"
    )
    
    type CategoryGorm struct {
        db *gorm.DB
    }
    
    func paginate(value interface{}, pagination *pkg.Pagination, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
        var totalRows int64
        db.Model(value).Count(&totalRows)
        pagination.TotalRows = totalRows
        totalPages := int(math.Ceil(float64(totalRows) / float64(pagination.PageSize)))
        pagination.TotalPages = totalPages
        return func(db *gorm.DB) *gorm.DB {
            return db.Offset(pagination.GetOffset()).Limit(pagination.GetLimit()).Order(pagination.GetSort())
        }
    }
    
    type Category struct {
        Id   int    `json:"id"`
        Type string `json:"type"`
    }
    
    func Server() {
        db, err := gorm.Open(sqlite.Open("category.db"), &gorm.Config{})
        if err != nil {
            panic(err)
        }
        err = db.AutoMigrate(&Category{})
        if err != nil {
            panic(err)
        }
        c := CategoryGorm{db: db}
    
        var engine = gin.Default()
        engine.POST("/api/v1/category", c.AddCategory)
        engine.GET("/api/v1/category", c.CategoryList)
    
        panic(engine.Run(":9000"))
    }
    
    func (g CategoryGorm) AddCategory(c *gin.Context) {
        var req Category
        err := c.Bind(&req)
        if err != nil {
            log.Printf("parameters err for: %s", err.Error())
        }
        err = g.db.Model(&Category{}).Create(&req).Error
        if err != nil {
            log.Printf("insert category into db failed for: %s", err)
            return
        }
        c.JSON(200, "success")
    }
    
    func (cg *CategoryGorm) CategoryList(c *gin.Context) {
        var req pkg.Pagination
        err := c.Bind(&req)
        if err != nil {
            log.Printf("parameters error %s", err)
            return
        }
        list, err := cg.List(req)
        if err != nil {
            log.Printf("query category list failed for: %s", err)
        }
        c.JSON(200, list)
    }
    
    func (cg *CategoryGorm) List(pagination pkg.Pagination) (*pkg.Pagination, error) {
        var categories []*Category
        cg.db.Scopes(paginate(categories, &pagination, cg.db)).Find(&categories)
        pagination.Rows = categories
    
        return &pagination, nil
    }
    

    这里只是为了演示分页效果,使用简单的demo来完成。我们的代码里面是用了sqlite数据库,无需安装只需要本地创建文件即可。
    运行以上代码,首先我们调用以下POST请求创建多个数据库category对象共查询:



    接着调用以下分页查询看看效果:

    http://localhost:9000/api/v1/category?pageIndex=1&pageSize=3
    

    输出:

    {
        "pageSize": 3,
        "pageIndex": 1,
        "sort": "Id desc",
        "total_rows": 7,
        "total_pages": 3,
        "rows": [
            {
                "id": 8,
                "type": "desk"
            },
            {
                "id": 7,
                "type": "joy"
            },
            {
                "id": 6,
                "type": "hat"
            }
        ]
    }
    

    达到分页效果。

    相关文章

      网友评论

          本文标题:Gorm scope实现分页

          本文链接:https://www.haomeiwen.com/subject/nwksprtx.html