Gorm Preload使用疑问及报错:无法为model.Currency预加载currencies字段
嘿,我来帮你搞明白GORM里Preload到底咋用,还有你为啥会碰到那个报错~
先搞懂Preload的核心用途
GORM的Preload可不是用来预加载当前模型本身的,它的核心作用是一次性预加载模型的关联数据,专门解决烦人的N+1查询问题。简单说:当你的结构体里定义了和其他模型的关联(比如一对多、多对一这类关系),用Preload可以在查询主模型的时候,把关联的子模型数据也一起查出来,不用等你后续访问关联字段时再单独发SQL请求。
你的报错原因
你现在的Currency结构体里完全没有任何关联字段(比如没有Accounts []Account或者属于某个其他模型的字段),却调用了Preload("currencies")——GORM在Currency模型里找不到叫currencies的关联字段,自然就会报错:can't preload field currencies for model.Currency。而且你本来就是要查询Currency本身,根本不需要用Preload,直接用Find就够了,这也是你第二段Find代码能正常跑的原因。
正确使用Preload的示例
给你举个实际场景的例子,假设你有个Account模型和Currency是关联的:
package model type Currency struct { ID uint64 `gorm:"primary_key"` CurrencyCode string `gorm:"size:3"` // 定义一对多关联:一个币种对应多个账户 Accounts []Account `gorm:"foreignKey:CurrencyID"` } type Account struct { ID uint64 `gorm:"primary_key"` UserName string CurrencyID uint64 // 外键,关联Currency的ID Currency Currency `gorm:"references:ID"` // 定义多对一关联:账户属于某个币种 }
这时候,如果要查询所有账户,同时把每个账户对应的币种信息也一起查出来,就该用Preload了:
var accounts []model.Account // 预加载Account模型里的Currency关联字段 dbMySQL.Preload("Currency").Find(&accounts) // 遍历的时候直接访问account.Currency就行,不会再触发新的SQL查询 for _, account := range accounts { fmt.Printf("用户%s使用的币种是%s\n", account.UserName, account.Currency.CurrencyCode) }
反过来,如果你要查询所有币种,同时预加载每个币种对应的所有账户:
var currencies []model.Currency dbMySQL.Preload("Accounts").Find(¤cies) for _, curr := range currencies { fmt.Printf("币种%s下共有%d个账户\n", curr.CurrencyCode, len(curr.Accounts)) }
你的问题解决办法
- 直接删掉你代码里的
Preload("currencies"),因为你查询的就是Currency本身,没有任何关联字段需要预加载,直接用dbMySQL.Find(&preloadCurrencies)就完全可以了。 - 以后要使用
Preload的时候,记得它的参数是模型里定义的关联字段名称(比如上面的"Currency"或者"Accounts"),不是表名或者模型名。
内容的提问来源于stack exchange,提问作者Patryk
相关产品推荐
相关产品推荐

