有一个(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)
来源:oschina
链接:https://my.oschina.net/u/1248114/blog/3047501