Gorm仅插入Wallet条目,其余AccountType未创建的问题咨询
问题分析与解决方案
嘿,我一眼就揪出问题所在了——你对GORM的First方法的用法理解跑偏啦!
你当前写的db.First(&acccountTypeModelWallet)并不是按照你设置的Type和Name字段去查询匹配的记录,而是会直接查询表中的第一条记录,然后把这条记录的所有字段值覆盖到你的结构体变量里。咱们顺着你的代码走一遍就能明白为啥只有Wallet被创建了:
- 第一次执行Wallet的逻辑时,数据库是空的,
db.First找不到任何记录,触发RecordNotFound(),所以成功创建了Wallet条目。 - 轮到Bank Account的逻辑时,数据库里已经有了Wallet这条记录,
db.First(&acccountTypeModelBankAccount)会把Wallet的Type和Name直接赋值给你的acccountTypeModelBankAccount变量,这时候RecordNotFound()返回false,自然就跳过了创建步骤。 - Exchange Account的逻辑也是完全一样的道理,所以这两个条目都不会被创建。
修复方案
有两种靠谱的方式解决这个问题:
方式1:明确指定查询条件
用Where搭配First,告诉GORM你要根据Type(或者Type+Name)去查询记录:
acccountTypeModelWallet := accounttypes.AccountType{Type: "wallet", Name: "Wallet"} if db.Where(&acccountTypeModelWallet).First(&acccountTypeModelWallet).RecordNotFound() { fmt.Println("Account Type `Wallet` not found. Creating..") err := db.Create(&acccountTypeModelWallet).Error if err != nil { return false, err } } // Bank Account 部分同理修改 acccountTypeModelBankAccount := accounttypes.AccountType{Type: "bankaccount", Name: "Bank Account"} if db.Where(&acccountTypeModelBankAccount).First(&acccountTypeModelBankAccount).RecordNotFound() { fmt.Println("Account Type `Bank Account` not found. Creating..") err := db.Create(&acccountTypeModelBankAccount).Error if err != nil { fmt.Println(err) return false, err } } // Exchange Account 部分同理修改 acccountTypeModelExchange := accounttypes.AccountType{Type: "exchange", Name: "Exchange Account"} if db.Where(&acccountTypeModelExchange).First(&acccountTypeModelExchange).RecordNotFound() { fmt.Println("Account Type `Exchange Account` not found. Creating..") err := db.Create(&acccountTypeModelExchange).Error if err != nil { return false, err } }
如果你想更精准地指定查询字段(比如只按Type查询),也可以写成:
if db.First(&acccountTypeModelWallet, "type = ?", "wallet").RecordNotFound() { // 创建逻辑 }
方式2:用FirstOrCreate简化代码
GORM提供了FirstOrCreate方法,直接一步完成“查询不存在则创建”的逻辑,比手动判断更简洁也更不容易出错:
// Wallet 部分 acccountTypeModelWallet := accounttypes.AccountType{Type: "wallet", Name: "Wallet"} // 第二个参数是查询条件,按Type字段匹配 db.FirstOrCreate(&acccountTypeModelWallet, accounttypes.AccountType{Type: "wallet"}) // Bank Account 部分 acccountTypeModelBankAccount := accounttypes.AccountType{Type: "bankaccount", Name: "Bank Account"} db.FirstOrCreate(&acccountTypeModelBankAccount, accounttypes.AccountType{Type: "bankaccount"}) // Exchange Account 部分 acccountTypeModelExchange := accounttypes.AccountType{Type: "exchange", Name: "Exchange Account"} db.FirstOrCreate(&acccountTypeModelExchange, accounttypes.AccountType{Type: "exchange"})
这个方法会先根据第二个参数的条件查询记录,找到就把数据赋值给第一个参数的结构体;找不到就用第一个参数的结构体创建新记录,完美适配你的需求。
内容的提问来源于stack exchange,提问作者Tino
相关产品推荐
相关产品推荐

