gorm 关系 has one 有一个

﹥>﹥吖頭↗ 提交于 2020-04-15 10:05:02

【推荐阅读】微服务还能火多久?>>>

有一个(has one)关联也建立了与另一个模型的一对一连接,但有一些不同的语义(和后果)。此关联表示模型的每个实例包含或拥有另一个模型的一个实例。

例如,如果您的应用程序包括用户和信用卡以及每个用户 只能有一张信用卡。

定义模型:

// User has one CreditCard, UserID is the foreign key
// User 有一个 CreditCard,UserId 是外键
type CreditCard struct {
  gorm.Model
  Number   string
  UserID   uint
}

type User struct {
  gorm.Model
  CreditCard   CreditCard
}

credit_cards 表的 user_id 列是外键,它引用 users 表的 id 列。

has one 关系和 belongs to 关系其实是一会事,所有者有一个附属者,附属者属于一个所有者,User 有一个 CreditCard,CreditCard 属于一个 User。

区别在于定义模型时,has one 关系,把附属者 CreditCard 作为所有者 User 的一个字段,更自然;而 belongs to 关系,把所有者 User 作为附属者 CreditCard 的一个字段。

外键

对于 has one 关系,外键字段也必须存在,所有者将会保存它模型的主键到此外键中。这里是 users 的主键 id 将保存在 credit_cards 表的外键 user_id 中。

外键字段名经常等于所有者的类型 + 所有者的主键,对于上面的示例,它是 User + ID = UserID。

当你把一个 CreditCard 给那个 User,CreditCard 将会保存 User 的 ID 到它的 UserID 字段。

如果你想要使用另一字段保存这个关系,你可以用 tag foreignkey 来修改它,比如:

type CreditCard struct {
  gorm.Model
  Number   string
  UserName string
}

type User struct {
  gorm.Model
  Name string
  CreditCard CreditCard `gorm:"foreignkey:UserName"`
}

把 credit_cards 表的外键改成 user_name(默认为 user_id)。tag 需要写在所有者结构体的类型为从属者的字段上,这里是 User 的 CreditCard 字段。

关联外键

关联外键指与外键有关联的键,被外键所引用的键。

默认,所有者实体将会保存模型的主键到外键,你可以更改以保存另一个字段到外键,比如下面例子中改成了 Name 字段。

type CreditCard struct {
  gorm.Model
  Number string
  UID    string
}

type User struct {
  gorm.Model
  Name       `sql:"index"`
  CreditCard CreditCard `gorm:"foreignkey:uid;association_foreignkey:name"`
}

外键改成 uid,关联外键改成 name。

创建记录

一起创建 User 和 CreditCard

u1 := &User{
	Name: "swt",
	CreditCard: CreditCard{
		Number: "110",
	},
}
db.Create(u1)

当 u1 的 CreditCard 不为空时,db.Create(u1) 调用在 users 表创建 u1 记录后,又在 credit_cards 表中创建 u1.CreditCard 记录。之后 u1 及 u1.CreditCard 各个字段被填上正确的值。

分别创建 User 和 CreditCard

u3 := &User{
	Name: "swt",
}
db.Create(u3)
u3.CreditCard.Number = "189"
u3.CreditCard.UserID = u3.ID
db.Create(&u3.CreditCard)

当 u3 的 CreditCard 为空时,db.Create(u3) 调用在 users 表创建 u3 记录后,不会在 credit_cards 表创建记录。

查找记录

你可以用 Related 方法查找 has one 关系。

user := &User{}
user.ID = 2
var card CreditCard
db.Model(user).Related(&card, "CreditCard")
//// SELECT * FROM credit_cards WHERE user_id = 2;

// Related 方法第二个参数 "CreditCard" 是 user 的字段名,
// 意味着获取 user 的 CreditCard 关系,然后填充到变量 card 中。

// 如果 CreditCard 的外键字段为 UserID, 则能省略第二个参数,自动查找关系,如
db.Model(user).Related(&card)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!