一架梯子,一头程序猿,仰望星空!

GORM 关联查询 - 一对一关系(has one)


GORM的关联查询(又叫连表查询)中的Has One关系是一对一关联关系的一种,通常用于描述一个Model拥有另外一个Model。

提示:Has one很像属于(belongs to)关系,都是一对一关系,区别是Has One关系和属于关系,持有关联Model属性的关系是相反的,例如:A 关联 B,Has One关系通常是A 结构体持有B属性, belongs to关系则是B结构体持有A

例子

每一个用户都有一张信用卡,下面以Go Struct表示表结构

// 信用卡
type CreditCard struct {
  // 继承gorm的基础Model,里面默认定义了ID、CreatedAt、UpdatedAt、DeletedAt 4个字段
  gorm.Model
  Number   string
  UserID   uint // 外键
}

// 用户
type User struct {
  gorm.Model
  CreditCard   CreditCard // 持有信用卡属性(关联信用卡)
}

外键

关联查询必须包含外键,默认情况下Has One关系的外键由持有关联属性的类型名 + 主键 组成外键名,如上例,User关联CreditCard的外键就是User + ID = UserID。

通过下面方式可以自定义外键

type CreditCard struct {
  gorm.Model
  Number   string
  UserName string // 外键
}

type User struct {
  gorm.Model
  // 通过标签将外键定义为:UserName
  CreditCard CreditCard `gorm:"foreignkey:UserName"`
}

关联外键

默认情况下,保存User的时候,会自动将User的主键保存到外键UserID中,关联查询的时候,也会使用外键和关联外键进行关联进行查询,这里User的ID就是关联外键。

自定义关联外键的例子

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

type User struct {
  gorm.Model
  Name       `sql:"index"` // 关联外键
  // 自定义关联外键为:name
  CreditCard CreditCard `gorm:"foreignkey:uid;association_foreignkey:name"`
}

关联查询例子

user := User{}
// 查询用户数据
//自动生成sql: SELECT * FROM `users`  WHERE (username = 'tizi365') LIMIT 1
db.Where("username = ?", "tizi365").First(&user)
fmt.Println(user)

var card CreditCard
////自动生成SQL: SELECT * FROM credit_cards WHERE user_id = 123; // 123 自动从user的ID读取
// 关联查询的结果会填充到card变量
db.Model(&user).Related(&card, "CreditCard")

// Related第二个参数是外键,如果使用默认外键,或者预定义外键,可以忽略第二个参数
db.Model(&user).Related(&card)

// 上面的例子将关联查询的结果保存到外部变量,user.CreditCard属性值是空的。
// 可以直接将结果保存到user.CreditCard属性
db.Model(&user).Related(&user.CreditCard)