在数据库上的每个 api 调用中,gorm 作用域不断添加到前一个

on every api call on db, gorm scope keep adding to previous one

下面是我的 api 处理程序。 首先 运行 它给了我正确的输出并且在 db 中相应的调用也是正确的。

2020-07-04 14:51:04.512 IST [32129] postgres@postgres LOG:  execute <unnamed>: SELECT count(*) FROM "access_owners"  WHERE ("access_owners"."area" = )
2020-07-04 14:51:04.512 IST [32129] postgres@postgres DETAIL:  parameters:  = '4th Floor'
2020-07-04 14:51:04.513 IST [32129] postgres@postgres LOG:  execute <unnamed>: SELECT * FROM "access_owners"  WHERE ("access_owners"."area" = ) LIMIT 10 OFFSET 2
2020-07-04 14:51:04.513 IST [32129] postgres@postgres DETAIL:  parameters:  = '4th Floor'

这是我得到的API响应

{
    "skip": 2,
    "limit": 10,
    "total": 3,
    "resources": [
        {
            "id": 26,
            "name": "Test_User_5",
            "email": "test_user_5@gmailcom",
            "area": "4th Floor"
        }
    ]
}

但是,如果我使用相同的参数再次调用相同的 API,它会错误地在数据库中再添加一个 where 条件。

2020-07-04 14:51:22.560 IST [32129] postgres@postgres LOG:  execute <unnamed>: SELECT count(*) FROM "access_owners"  WHERE ("access_owners"."area" = ) AND ("access_owners"."area" = ) LIMIT 10 OFFSET 2
2020-07-04 14:51:22.560 IST [32129] postgres@postgres DETAIL:  parameters:  = '4th Floor',  = '4th Floor'

这是我得到的错误

sql: no rows in result set

这是我的 API 处理程序

func GetAccessOwners(db *gorm.DB) echo.HandlerFunc {
    return func(c echo.Context) error {
        page := new(models.ResourcePage)
        var ao = new(models.AccessOwner)
        var err error
        if err = c.Bind(ao); err != nil {
            return err
        }
        var skip int
        var limit int
        skipParam := c.QueryParam("skip")
        limitParam := c.QueryParam("limit")
        if strings.TrimSpace(skipParam) != "" {
            skip, err = strconv.Atoi(skipParam)
            if err != nil {
                return merry.Wrap(err)
            }
        } else {
            skip = 0
        }

        if strings.TrimSpace(limitParam) != "" {
            limit, err = strconv.Atoi(limitParam)
            if err != nil {
                return merry.Wrap(err)
            }
        } else {
            limit = 10
        }
        accessOwners := []models.AccessOwner{}
        page.Resources = []models.AccessOwner{}
        page.Skip = skip
        page.Limit = limit
        

        db = db.Scopes(GetCount(*ao)).Model(page.Resources).Count(&page.Total)
        db = db.Offset(skip)
        db = db.Limit(limit)
        if err := db.Find(&accessOwners).Error; err != nil {
            return merry.Wrap(err)
        }

        page.Resources = accessOwners
        return c.JSON(201, page)

    }
}

func GetCount(ao models.AccessOwner) func(db *gorm.DB) *gorm.DB {
    return func(db *gorm.DB) *gorm.DB {
        return db.Where(ao)
    }

来自doc

When using multiple immediate methods with GORM, later immediate method will reuse before immediate methods’s query conditions

你设置的是db 所以第一个请求的第二个请求查询条件已经存在db.

db = db.Scopes(GetCount(*ao)).Model(page.Resources).Count(&page.Total)
db = db.Offset(skip)
db = db.Limit(limit)

所以,不要设置 db 而是可以链接多个操作或单独使用

db.Scopes(GetCount(*ao)).Model(page.Resources).Count(&page.Total)
                   .Offset(skip).Limit(limit).Find(&accessOwners)