Golang Gorm作用域从v1升级到v2后损坏



我使用的是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] [rows:2] SELECT * FROMgenresLIMITsql:在Scan中期望有9个目标参数,而不是1个;[GIN] 2022/06/18 - 00:41:00 | 400 | 1.5205ms | 127.0.0.1 | GET "/api/v1/genres"错误#01:sql: Scan中预期有9个目标参数,而不是1个;sql:在Scan中期望9个目标参数,而不是1

现在,我发现错误是由于这一行:db.Model(entity).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{})

希望每个人都使用自己的会话,但似乎不起作用。

有什么建议吗?

万一有人需要的话:

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

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获取计数,这不会影响return db.Offset(p.Offset).Limit(p.PerPage).Session(&gorm.Session{})

*db.Gorm参数的后续使用。

最新更新