table 引用一个 table,后者又引用另一个 table

table references a table which in turn references another table

我正在使用 gorm,我有这样的结构,其中 User table 包含引用 Address 的外键,然后引用 Country.

   type User struct {
      ID              int       `gorm:"column:id; primaryKey; autoIncrement" json:"id"`
      Address         Address
      AddressID       int  `gorm:"column:address_id;foreignKey:AddressID;references:ID" json:"address"`
   }

   type Address struct {
      ID          int `gorm:"column:ID;primaryKey;autoIncrement;" json:"id"`
      CountryCode int `gorm:"column:country_code; foreignKey:CountryCode; references:Code" json:"country_code"`
      Country     Country
   }

   type Country struct {
      Code          int    `gorm:"column:code; primaryKey; autoIncrement" json:"code"`
      Name          string `gorm:"column:name" json:"name"`
      ContinentName string `gorm:"column:continent_name" json:"continentName"`
   }

照片说明关系:

现在当我 return 一个用户使用:

  db.Model(&user).Where().First()  // or Find()

我得到地址,国家为空,像这样:

   {
    ID: 1,
    AddressID: 2,
    Address: {
          // empty address.
      }

   }

我确实为我创建了重新填充 AddressCountry 记录的函数,类似于:


func PopulateUser(user) User {

   addr = FindAddresByID(user.ID)
   cntr = FindCountryByCode(addr.Code)

   addr.Country = cntr
   user.Address = addr

   return user

}

但我的问题:

  1. Gorm 中是否有一个函数可以在我不创建函数的情况下为我执行此操作?
  2. 在这种情况下协会可以提供帮助吗?
  3. 如果我想在用户删除时删除地址,我如何在Gorm中做到这一点?

我试图自己寻找答案,但文档有点乱。

documentation 显示了结构引用中的外键标签。 也就是说,在您的情况下,它们应该位于地址和国家/地区,而不是地址 ID 和国家/地区代码。类似于:

type User struct {
      Address         Address `gorm:"foreignKey:AddressID;references:ID"`
      AddressID       int  `gorm:"column:address_id"`
   }

type Address struct {
      CountryCode int `gorm:"column:country_code"`
      Country     Country gorm:"foreignKey:CountryCode; references:Code"`
   }

请尝试这些。

为了

  1. 请参阅预先加载here
db.Preload("User").Preload("Address").Find(&users)
  1. 您可以在列上使用 cascade 标签。
type User struct {
  gorm.Model
  Name      string
  CompanyID int
  Company   Company `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}