Gorm事务中Association关联查询失效但count正常,应如何解决?
问题根因
你遇到的关联查询不生效和事务本身没有关系,是代码写法错误导致的,该需求完全可以在单个事务中完成,无需编写原生SQL。
你遇到的Count正常、查询失效的现象,是因为Count方法不需要接收返回数据集,只执行统计逻辑,所以不受入参错误的影响,具体问题如下:
- Association.Find方法入参类型错误:你的
TagModel.BookModels是[]BookModel切片类型,但你调用Find时传入的是单个&BookModel{}结构体指针,Gorm无法把多条关联数据写入单个结构体,自然拿不到结果。 - 缺少错误判断与事务回滚逻辑:当前代码没有处理
Begin、First、Commit等操作的返回错误,一旦中间步骤出错无法感知,也不会回滚事务,容易产生脏数据。 - 没有定义变量接收查询结果:你调用Find时直接传入了临时创建的结构体,就算查询成功也无法拿到返回的关联数据。
修正后代码示例
// 初始化接收结果的切片 var bookList []BookModel var count int64 tx := db.Begin() if tx.Error != nil { // 事务启动失败处理逻辑 return tx.Error } // 异常场景自动回滚 defer func() { if r := recover(); r != nil { tx.Rollback() } }() if tag != "" { var tagModel TagModel // 增加查询错误判断 if err := tx.Where(TagModel{Tag: tag}).First(&tagModel).Error; err != nil { tx.Rollback() return err } if tagModel.ID != 0 { // 传入切片指针接收关联数据 if err := tx.Model(&tagModel).Association("BookModels").Find(&bookList); err != nil { tx.Rollback() return err } count = tx.Model(&tagModel).Association("BookModels").Count() } } if err := tx.Commit().Error; err != nil { return err } // 后续直接操作bookList即可拿到关联的书籍数据
Preload写法示例(事务内同样生效)
如果你更倾向用Preload实现关联查询,事务内的写法如下:
var tagModel TagModel // Preload会自动关联查询BookModels数据写入结构体字段 if err := tx.Preload("BookModels").Where(TagModel{Tag: tag}).First(&tagModel).Error; err != nil { tx.Rollback() return err } count = int64(len(tagModel.BookModels))
内容的提问来源于stack exchange,提问作者Dansekongen
相关产品推荐
相关产品推荐

