一对一

原文:https://gorm.io/docs/has_one.html

一对一 Has One

A has one association sets up a one-to-one connection with another model, but with somewhat different semantics (and consequences). This association indicates that each instance of a model contains or possesses one instance of another model.

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

For example, if your application includes users and credit cards, and each user can only have one credit card.

​ 例如,如果你的应用包括用户和信用卡,并且每个用户可以只有一个信用卡。

声明 Declare

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// User有一个CreditCard,UserID是外键 User has one CreditCard, UserID is the foreign key
type User struct {
  gorm.Model
  CreditCard CreditCard
}

type CreditCard struct {
  gorm.Model
  Number string
  UserID uint
}

检索 Retrieve

1
2
3
4
5
6
// 使用预加载获取用户列表及其信用卡 Retrieve user list with eager loading credit card
func GetAll(db *gorm.DB) ([]User, error) {
  var users []User
  err := db.Model(&User{}).Preload("CreditCard").Find(&users).Error
  return users, err
}

覆盖外键 Override Foreign Key

For a has one relationship, a foreign key field must also exist, the owner will save the primary key of the model belongs to it into this field.

​ 对于has one关系,外键字段也必须存在,所有者将模型所属的主键保存到该字段中。

The field’s name is usually generated with has one model’s type plus its primary key, for the above example it is UserID.

​ 字段的名称通常是has one模型的类型加上其主键,例如上面的示例中的UserID

When you give a credit card to the user, it will save the User’s ID into its UserID field.

​ 当你给用户一张信用卡时,它会将用户的ID保存到其UserID字段中。

If you want to use another field to save the relationship, you can change it with tag foreignKey, e.g:

​ 如果你想使用另一个字段来保存关系,你可以使用标签foreignKey更改它,例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type User struct {
  gorm.Model
  CreditCard CreditCard `gorm:"foreignKey:UserName"`
  // 使用UserName作为外键 use UserName as foreign key
}

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

覆盖引用 Override References

By default, the owned entity will save the has one model’s primary key into a foreign key, you could change to save another field’s value, like using Name for the below example.

​ 默认情况下,拥有的实体将has one模型的主键保存到一个外键中,你可以更改为保存另一个字段的值,例如使用下面的示例中的Name

You are able to change it with tag references, e.g:

​ 你可以使用标签references更改它,例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type User struct {
  gorm.Model
  Name       string     `gorm:"index"`
  CreditCard CreditCard `gorm:"foreignKey:UserName;references:name"`
}

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

多态关联 Polymorphism Association

GORM supports polymorphism association for has one and has many, it will save owned entity’s table name into polymorphic type’s field, primary key into the polymorphic field

​ GORM支持has onehas many的多态关联,它将拥有的实体的表名保存到多态类型的字段中,主键保存到多态字段中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
type Cat struct {
  ID    int
  Name  string
  Toy   Toy `gorm:"polymorphic:Owner;"`
}

type Dog struct {
  ID   int
  Name string
  Toy  Toy `gorm:"polymorphic:Owner;"`
}

type Toy struct {
  ID        int
  Name      string
  OwnerID   int
  OwnerType string
}

db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}})
// INSERT INTO `dogs` (`name`) VALUES ("dog1")
// INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs")

You can change the polymorphic type value with tag polymorphicValue, for example:

​ 你可以使用标签polymorphicValue更改多态类型值,例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
type Dog struct {
  ID   int
  Name string
  Toy  Toy `gorm:"polymorphic:Owner;polymorphicValue:master"`
}

type Toy struct {
  ID        int
  Name      string
  OwnerID   int
  OwnerType string
}

db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}})
// INSERT INTO `dogs` (`name`) VALUES ("dog1")
// INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","master")

CRUD与Has One的关系 CRUD with Has One

Please checkout Association Mode for working with has one relations

​ 请查看关联模式以处理has one关系

预加载(Eager Loading) Eager Loading

GORM allows eager loading has one associations with Preload or Joins, refer Preloading (Eager loading) for details

​ GORM允许使用PreloadJoins进行预加载has one关联,详情请参考预加载(Eager loading)

Self-Referential Has One

1
2
3
4
5
6
type User struct {
  gorm.Model
  Name      string
  ManagerID *uint
  Manager   *User
}

FOREIGN KEY Constraints

You can setup OnUpdate, OnDelete constraints with tag constraint, it will be created when migrating with GORM, for example:

​ 你可以使用标签constraint设置OnUpdateOnDelete约束,当使用GORM进行迁移时,它将被创建,例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
type User struct {
  gorm.Model
  CreditCard CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

type CreditCard struct {
  gorm.Model
  Number string
  UserID uint
}

You are also allowed to delete selected has one associations with Select when deleting, checkout Delete with Select for details

​ 你还可以使用Select在删除时选择删除特定的has one关联,详情请参考Delete with Select

最后修改 October 10, 2024: 更新 (a4b8f85)