duanhuan7750 2018-01-17 22:35
浏览 87

gorm.DB可以自动解析外键吗?

I'm trying to use https://github.com/jinzhu/gorm to automatically map foreign keys for me but somehow either I'm doing it wrong or the library cannot do it and I'm in the wrong.

I have the following structs:

type Currency struct {
  ID           uint64 `gorm:"primary_key"`
  CurrencyCode string `gorm:"size:3"`
}

type Rate struct {
  ID          uint64 `gorm:"primary_key"`
  CurrencyID  uint64
  Currency    Currency `gorm:"ForeignKey:CurrencyID"`
  Price       float64
}

and the following SQL tables (edited so that currency_code is unique)

CREATE TABLE `rates` (
  `id` serial PRIMARY KEY,
  `currency_id` bigint unsigned NOT NULL,
  `price` decimal(12,2) NOT NULL,
  CONSTRAINT `fk_rate_currency`
    FOREIGN KEY (currency_id) REFERENCES currencies(id)
);

CREATE TABLE `currencies` (
  `id` serial PRIMARY KEY,
  `currency_code` char(3) NOT NULL UNIQUE
);

Now I thought that when I do something like this:

rate := Rate{
  Currency: Currency{
    CurrencyCode: "USD",
  },
  Price: 123,
}
db, _  := gorm.Open("mysql", ...)
db.Create(&rate)

then "USD" would get automatically mapped to a currency_id but instead it inserts new "USD" entry in currencies table for every db.Create(&rate)

Am I doing it wrong or it's the library?

EDIT

I know that I can do it by querying the DB for currency ID

curr := db.Currency{}
db.Where("currency_code = ?", "USD").First(&curr)
// use curr with proper ID

but then:

  • I have to make 2 DB calls
  • I don't use gorm's foreign key mapping feature (if there is one)
  • 写回答

1条回答 默认 最新

  • douyou7797 2018-01-18 09:23
    关注

    In their documentation it states:

    By default when creating/updating a record, GORM will save its associations, if the association has primary key, GORM will call Update to save it, otherwise it will be created.

    So when you want to map to a certain entry you must correlate it with the ID, otherwise it will create a new record.

    In your case you could use the currency_code as the PRIMARY KEY for Currency (use fixed number of chars to make it faster, not varchar, like sql:"type:char(3);unique").

    This would eliminate the need of a search by ID anymore, it would just find "USD" as primary key and use it => no more multiple records per currency. Also if there is a currency that it does not have, it will create it in the Currency table.

    Also you can eliminate the gorm:"ForeignKey:CurrencyID" struct tag and let GORM create it's own tables with AutoMigrate, and would create the tables with the appropriate FK:

    db := gorm.Open("mysql", ...)
    db.Set("gorm:table_options", "ENGINE=InnoDB")
    db.Set("gorm:table_options", "collation_connection=utf8_general_ci")
    // Migrate the schema
    db.AutoMigrate(&models.Currency{})
    db.AutoMigrate(&models.Rate{})
    
    评论

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大