英文:
AutIncrement doesnt work for me with GORM
问题
当我运行以下代码时,我一遍又一遍地收到这个错误消息:
/Sites/importer/import.go:142 Error 1062: Duplicate entry '112' for key 'products.PRIMARY'
我尝试过使用gorm.Model
和不使用它,但都没有帮助。在INSERT语句中生成的ID不会改变。
谢谢。
Adrian
package main
import (
"encoding/csv"
"log"
"gorm.io/datatypes"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"os"
"strconv"
)
var merchant_feeds []MerchantFeed
var merchant_csv_mappings []MerchantCsvMapping
type MerchantFeed struct {
// gorm.Model
ID int `gorm:"primary_key"`
MerchantID int
}
type MerchantCsvMapping struct {
// gorm.Model
ID int `gorm:"primary_key"`
MerchantId int
Name string
ProductNo string
PriceOld string
Ean string
Price string
Category int
DeepLink string
ShortDescription string
LongDescription string
BrandMerchant int
MerchantImageURL string
AlternateImage string
GalleryImage int
GalleryImage2 int
GalleryImage3 int
GalleryImage4 int
DeliveryTime string
DeliveryCost string
}
type Product struct {
// gorm.Model
ID int `gorm:"primary_key"`
MerchantId int
Name string
Slug string
ProductNo string
PriceOld string
Tags datatypes.JSON
Price string
Discount int
Ean string
DeepLink string
ShortDescription string
LongDescription string
MerchantImageUrl string
AlternateImage string
DeliveryTime string
DeliveryCost string
}
func main() {
db, err := gorm.Open(mysql.Open("root@tcp(127.0.0.1:3306)/myshop?parseTime=true"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.Find(&merchant_feeds, 7)
for _, feed := range merchant_feeds {
db.Where("merchant_id = ?", feed.MerchantID).Find(&merchant_csv_mappings)
importProducts(feed.MerchantID, feed.ID, merchant_csv_mappings, db)
}
}
func importProducts(MerchantID int, FeedID int, CsvMapping []MerchantCsvMapping, db *gorm.DB) {
path := strconv.Itoa(MerchantID) + "-" + strconv.Itoa(FeedID) + "-feed.csv"
products := readCsvFile(path)
i := 0
var product Product
for _, p := range products {
if i == 0 {
i++
continue
}
mapping := CsvMapping[0]
product.MerchantId = MerchantID
idx2, _ := strconv.Atoi(string(mapping.Name))
product.Name = p[idx2]
idx3, _ := strconv.Atoi(string(mapping.ProductNo))
product.ProductNo = p[idx3]
idx4, _ := strconv.Atoi(string(mapping.PriceOld))
product.PriceOld = p[idx4]
idx5, _ := strconv.Atoi(string(mapping.Price))
product.Price = p[idx5]
idx6, _ := strconv.Atoi(string(mapping.Ean))
product.Ean = p[idx6]
idx7, _ := strconv.Atoi(string(mapping.DeepLink))
product.DeepLink = p[idx7]
idx8, _ := strconv.Atoi(string(mapping.ShortDescription))
product.ShortDescription = p[idx8]
idx9, _ := strconv.Atoi(string(mapping.LongDescription))
product.LongDescription = p[idx9]
idx10, _ := strconv.Atoi(string(mapping.MerchantImageURL))
product.MerchantImageUrl = p[idx10]
idx11, _ := strconv.Atoi(string(mapping.AlternateImage))
product.AlternateImage = p[idx11]
idx12, _ := strconv.Atoi(string(mapping.DeliveryTime))
product.DeliveryTime = p[idx12]
idx13, _ := strconv.Atoi(string(mapping.DeliveryCost))
product.DeliveryCost = p[idx13]
db.Create(&product)
log.Println(product.ID)
}
}
func readCsvFile(filePath string) [][]string {
f, err := os.Open(filePath)
if err != nil {
log.Fatal("Unable to read input file "+filePath, err)
}
defer f.Close()
csvReader := csv.NewReader(f)
records, err := csvReader.ReadAll()
if err != nil {
log.Fatal("Unable to parse file as CSV for "+filePath, err)
}
return records
}
英文:
When i run the following code, i get this error message over and over
/Sites/importer/import.go:142 Error 1062: Duplicate entry '112' for key 'products.PRIMARY'
I tried with gorm.Model
and without. Nothing helped.
The generated ID inside the INSERT statement dont change.
Regards
Adrian
import (
"encoding/csv"
"log"
"gorm.io/datatypes"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"os"
"strconv"
)
var merchant_feeds []MerchantFeed
var merchant_csv_mappings []MerchantCsvMapping
type MerchantFeed struct {
// gorm.Model
ID int `gorm:"primary_key"`
MerchantID int
}
type MerchantCsvMapping struct {
// gorm.Model
ID int `gorm:"primary_key"`
MerchantId int
Name string
ProductNo string
PriceOld string
Ean string
Price string
Category int
DeepLink string
ShortDescription string
LongDescription string
BrandMerchant int
MerchantImageURL string
AlternateImage string
GalleryImage int
GalleryImage2 int
GalleryImage3 int
GalleryImage4 int
DeliveryTime string
DeliveryCost string
}
type Product struct {
// gorm.Model
ID int `gorm:"primary_key"`
MerchantId int
Name string
Slug string
ProductNo string
PriceOld string
Tags datatypes.JSON
Price string
Discount int
Ean string
DeepLink string
ShortDescription string
LongDescription string
MerchantImageUrl string
AlternateImage string
DeliveryTime string
DeliveryCost string
}
func main() {
db, err := gorm.Open(mysql.Open("root@tcp(127.0.0.1:3306)/myshop?parseTime=true"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Read all enabled feeds
// db.Where("can_sync = ?", 1).Find(&merchantFeeds)
db.Find(&merchant_feeds, 7)
// spew.Dump(merchantFeeds)
for _, feed := range merchant_feeds {
//pull also the column mapping
db.Where("merchant_id = ?", feed.MerchantID).Find(&merchant_csv_mappings)
importProducts(feed.MerchantID, feed.ID, merchant_csv_mappings, db)
}
}
func importProducts(MerchantID int, FeedID int, CsvMapping []MerchantCsvMapping, db *gorm.DB) {
//read csv file
path := strconv.Itoa(MerchantID) + "-" + strconv.Itoa(FeedID) + "-feed.csv"
products := readCsvFile(path)
//a counter to leave out the first line
i := 0
//product is the one we generate and save
var product Product
//p is the product inside the loop
for _, p := range products {
if i == 0 {
i++
continue
}
mapping := CsvMapping[0]
product.MerchantId = MerchantID
idx2, _ := strconv.Atoi(string(mapping.Name))
product.Name = p[idx2]
idx3, _ := strconv.Atoi(string(mapping.ProductNo))
product.ProductNo = p[idx3]
idx4, _ := strconv.Atoi(string(mapping.PriceOld))
product.PriceOld = p[idx4]
idx5, _ := strconv.Atoi(string(mapping.Price))
product.Price = p[idx5]
idx6, _ := strconv.Atoi(string(mapping.Ean))
product.Ean = p[idx6]
idx7, _ := strconv.Atoi(string(mapping.DeepLink))
product.DeepLink = p[idx7]
idx8, _ := strconv.Atoi(string(mapping.ShortDescription))
product.ShortDescription = p[idx8]
idx9, _ := strconv.Atoi(string(mapping.LongDescription))
product.LongDescription = p[idx9]
idx10, _ := strconv.Atoi(string(mapping.MerchantImageURL))
product.MerchantImageUrl = p[idx10]
idx11, _ := strconv.Atoi(string(mapping.AlternateImage))
product.AlternateImage = p[idx11]
idx12, _ := strconv.Atoi(string(mapping.DeliveryTime))
product.DeliveryTime = p[idx12]
idx13, _ := strconv.Atoi(string(mapping.DeliveryCost))
product.DeliveryCost = p[idx13]
//spew.Dump(product)
db.Create(&product)
log.Println(product.ID)
//os.Exit(3)
}
}
func readCsvFile(filePath string) [][]string {
f, err := os.Open(filePath)
if err != nil {
log.Fatal("Unable to read input file "+filePath, err)
}
defer f.Close()
csvReader := csv.NewReader(f)
records, err := csvReader.ReadAll()
if err != nil {
log.Fatal("Unable to parse file as CSV for "+filePath, err)
}
return records
}```
</details>
# 答案1
**得分**: 1
你的变量的作用域在for循环之外。
在循环内部,你正在创建产品。
对于第一个产品,GORM不会向数据库发送ID,数据库将生成下一个可用的ID并返回。GORM将把生成的ID放入`product`中。
对于第二个产品,GORM将重用该ID,并尝试使用该ID创建另一个产品。数据库将告诉你,该ID已经存在。
请尝试使用以下代码:
```go
for _, p := range products {
var product Product
...
}
英文:
The scope of your variable is outside the for loop.
var product Product
for _, p := range products {
...
}
Inside the loop, you are creating the product.
For your first product, GORM send no ID to the database, the database will generate the next available ID and return it. GORM will put the generated ID into product
.
For your second product, GORM will reuse that ID and try to create another product with that ID. The database will tell you, that ID exists already.
Try this instead:
for _, p := range products {
var product Product
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论