从 v1 升级到 v2 后 Golang Gorm 范围被破坏
P粉005417748
P粉005417748 2024-02-03 17:53:53
0
1
470

我使用的是 Gorm v1。我的分页范围可以正常工作:

func Paginate(entity BaseEntity, p *Pagination) func(db *gorm.DB) *gorm.DB {
    return func(db *gorm.DB) *gorm.DB {
        var totalRows int64

        db.Model(entity).Count(&totalRows)
        
        totalPages := int(math.Ceil(float64(totalRows) / float64(p.PerPage)))
        p.TotalPages = totalPages
        p.TotalCount = int(totalRows)
        p.SetLinks(entity.ResourceName())

        return db.Offset(p.Offset).Limit(p.PerPage)
    }
}

以及我的称呼方式:

if err := gs.db.Scopes(entities.Paginate(genre, p)).Find(&gs.Genres).Error; err != nil {
        return errors.New(err.Error())
    }

同样,这曾经可以正常工作,直到我升级到 Gorm v2。现在我收到以下消息:

[0.204ms] [行:2] 从 genres LIMIT 2 中选择 * sql:扫描中预期有 9 个目标参数,而不是 1; sql:扫描中预期有 9 个目标参数,而不是 1[GIN] 2022/06/18 - 00:41:00 | 400 | 1.5205 毫秒 | 127.0.0.1 |获取“/api/v1/流派” 错误#01:sql:扫描中预期有 9 个目标参数,而不是 1; sql:扫描中预期有 9 个目标参数,而不是 1

现在,我发现错误是由于这一行引起的: db.Model(实体).Count(&totalRows) 因为如果我删除它,那么我的查询就会正确执行(显然 TotalPages 的数据不正确,因为它没有计算)。浏览文档,我看到https://gorm.io/docs/method_chaining.html#Multiple-Immediate-Methods,所以我的猜测是用于获取 totalRows 的连接正在被重用并且有一些残留数据,因此我的偏移量和限制查询正在失败。 我尝试为计数和偏移查询创建一个新会话: db.Model(entity).Count(&totalRows).Session(&gorm.Session{})

return db.Offset(p.Offset).Limit(p.PerPage).Session(&gorm.Session{})

希望每个人都能使用自己的会话,但似乎行不通。

有什么建议吗?

P粉005417748
P粉005417748

全部回复(1)
P粉465287592

如果有人需要它:

我确实必须创建一个新会话,但我没有以正确的方式创建它。我最终做了:

countDBSession := db.Session(&gorm.Session{Initialized: true})
countDBSession.Model(entity).Count(&totalRows)

效果正如预期的那样。所以我现在的范围是:

// Paginate is a Gorm scope function.
func Paginate(entity BaseEntity, p *Pagination) func(db *gorm.DB) *gorm.DB {
    return func(db *gorm.DB) *gorm.DB {

        var totalRows int64

        // we must create a new session to run the count, otherwise by using the same db connection
        // we'll get some residual data which will cause db.Offset(p.Offset).Limit(p.PerPage) to fail.
        countDBSession := db.Session(&gorm.Session{Initialized: true})
        countDBSession.Model(entity).Count(&totalRows)

        totalPages := int(math.Ceil(float64(totalRows) / float64(p.PerPage)))
        p.TotalPages = totalPages
        p.TotalCount = int(totalRows)
        p.SetLinks(entity.ResourceName())

        return db.Offset(p.Offset).Limit(p.PerPage)
    }
}

请注意,我正在使用新会话通过 countDBSession 获取计数,这不会影响 *db.Gorm 参数在 return db.Offset(p.Offset).Limit(p.PerPage) 的使用).Session(&gorm.Session{})

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!