Go语言学习笔记—gorm(三)

文章目录


一 关联—Belongs To

1.1 Belongs To

belongs to 会与另一个模型建立了一对一的连接。 这种模型的每一个实例都“属于”另一个模型的一个实例。

例如,您的应用包含 user 和 company,并且每个 user 能且只能被分配给一个 company。下面的类型就表示这种关系。 注意,在 User 对象中,有一个和 Company 一样的 CompanyID。 默认情况下, CompanyID 被隐含地用来在 UserCompany 之间创建一个外键关系, 因此必须包含在 User 结构体中才能填充 Company 内部结构体。

// `User` 属于 `Company`,`CompanyID` 是外键
type User struct {
   
  gorm.Model
  Name      string
  CompanyID int
  Company   Company
}

type Company struct {
   
  ID   int
  Name string
}

请参阅 预加载 以了解内部结构的详细信息。

1.2 重写外键

要定义一个 belongs to 关系,数据库的表中必须存在外键。默认情况下,外键的名字,使用拥有者的类型名称加上表的主键的字段名字

例如,定义一个User实体属于Company实体,那么外键的名字一般使用CompanyID。

GORM同时提供自定义外键名字的方式,如下例所示。

type User struct {
   
  gorm.Model
  Name         string
  CompanyRefer int
  Company      Company `gorm:"foreignKey:CompanyRefer"`
  // 使用 CompanyRefer 作为外键
}

type Company struct {
   
  ID   int
  Name string
}

1.3 重写引用

对于 belongs to 关系,GORM 通常使用数据库表,主表(拥有者)的主键值作为外键参考。 正如上面的例子,我们使用主表Company中的主键字段ID作为外键的参考值。

如果在Company实体中设置了User实体,那么GORM会自动把Company中的ID属性保存到User的CompanyID属性中。

同样的,您也可以使用标签 references 来更改它,例如:

type User struct {
   
  gorm.Model
  Name      string
  CompanyID string
  Company   Company `gorm:"references:Code"` // 使用 Code 作为引用
}

type Company struct {
   
  ID   int
  Code string
  Name string
}

NOTE GORM usually guess the relationship as has one if override foreign key name already exists in owner’s type, we need to specify references in the belongs to relationship.

type User struct {
   
  gorm.Model
  Name      string
  CompanyID string
  Company   Company `gorm:"references:CompanyID"` // use Company.CompanyID as references
}

type Company struct {
   
  CompanyID   int
  Code        string
  Name        string
}

1.4 Belongs to 的 CRUD

Please checkout Association Mode for working with belongs to relations

1.5 预加载

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

1.6 外键约束

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

type User struct {
   
  gorm.Model
  Name      string
  CompanyID int
  Company   Company `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

type Company struct {
   
  ID   int
  Name string
}

二 关联—Has One

2.1 Has One

has one 与另一个模型建立一对一的关联,但它和一对一关系有些许不同。 这种关联表明一个模型的每个实例都包含或拥有另一个模型的一个实例。

例如,您的应用包含 user 和 credit card 模型,且每个 user 只能有一张 credit card。

2.1.1 Declare

// User 有一张 CreditCard,UserID 是外键
type User struct {
   
  gorm.Model
  CreditCard CreditCard
}

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

2.1.2 Retrieve

// 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
}

2.2 重写外键

对于 has one 关系,同样必须存在外键字段。拥有者将把属于它的模型的主键保存到这个字段。

这个字段的名称通常由 has one 模型的类型加上其 主键 生成,对于上面的例子,它是 UserID

为 user 添加 credit card 时,它会将 user 的 ID 保存到自己的 UserID 字段。

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

type User struct {
   
  gorm.Model
  CreditCard CreditCard `gorm:"foreignKey:UserName"`
  // use UserName as foreign key
}

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

2.3 重写引用

默认情况下,拥有者实体会将 has one 对应模型的主键保存为外键,您也可以修改它,用另一个字段来保存,例如下个这个使用 Name 来保存的例子。

您可以使用标签 references 来更改它,例如:

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
}

2.4 多态关联

GORM 为 has onehas many 提供了多态关联支持,它会将拥有者实体的表名、主键值都保存到多态类型的字段中。

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")

您可以使用标签 polymorphicValue 来更改多态类型的值,例如:

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")

2.5 Has One 的 CURD

查看 关联模式 获取 has one 相关的用法

2.6 预加载

GORM 可以通过 PreloadJoins 预加载 has one 关联的记录,查看 预加载 获取详情

2.7 自引用 Has One

type User struct {
   
  gorm.Model
  Name      string
  ManagerID *uint
  Manager   *User
}

2.8 外键约束

你可以通过为标签 constraint 配置 OnUpdateOnDelete 实现外键约束,在使用 GORM 进行迁移时它会被创建,例如:

type User struct {
   
  gorm.Model
  CreditCard CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

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

你也可以在删除记录时通过 Select 来删除关联的记录,查看 Delete with Select 获取详情

三 关联—Has Many

3.1 Has Many

has many 与另一个模型建立了一对多的连接。 不同于 has one,拥有者可以有零或多个关联模型。

例如,您的应用包含 user 和 credit card 模型,且每个 user 可以有多张 credit card。

3.1.1 Declare

// User 有多张 CreditCard,UserID 是外键
type User struct {
   
  gorm.Model
  CreditCards []CreditCard
}

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

3.1.2 Retrieve

// Retrieve user list with edger loading credit cards
func GetAll(db *gorm.DB) ([]User, error) {
   
    var users []User
    err := db.Model(&User{
   }).Preload("CreditCards").Find(&users).Error
    return users, err
}

3.2 重写外键

要定义 has many 关系,同样必须存在外键。 默认的外键名是拥有者的类型名加上其主键字段名

例如,要定义一个属于 User 的模型,则其外键应该是 UserID

此外,想要使用另一个字段作为外键,您可以使用 foreignKey 标签自定义它:

type User struct {
   
  gorm.Model
  CreditCards []CreditCard `gorm:"foreignKey:UserRefer"`
}

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

3.3 重写引用

GORM 通常使用拥有者的主键作为外键的值。 对于上面的例子,它是 UserID 字段。

为 user 添加 credit card 时,GORM 会将 user 的 ID 字段保存到 credit card 的 UserID 字段。

同样的,您也可以使用标签 references 来更改它,例如:

type User struct {
   
  gorm.Model
  MemberNumber string
  CreditCards  []CreditCard `gorm:"foreignKey:UserNumber;references:MemberNumber"`
}

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

3.4 多态关联

GORM 为 has onehas many 提供了多态关联支持,它会将拥有者实体的表名、主键都保存到多态类型的字段中。

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

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

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

您可以使用标签 polymorphicValue 来更改多态类型的值,例如:

type Dog struct {
   
  ID   int
  Name string
  Toys []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"}, {
   Name: "toy2"}}})
// INSERT INTO `dogs` (`name`) VALUES ("dog1")
// INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","master"), ("toy2","1","master")

3.5 Has Many 的 CURD

查看 关联模式 获取 has many 相关的用法

3.6 预加载

GORM 可以通过 Preload 预加载 has many 关联的记录,查看 预加载 获取详情

3.7 自引用 Has Many

type User struct {
   
  gorm.Model
  Name      string
  ManagerID *uint
  Team      []User `gorm:"foreignkey:ManagerID"`
}

3.8 外键约束

你可以通过为标签 constraint 配置 OnUpdateOnDelete 实现外键约束,在使用 GORM 进行迁移时它会被创建,例如:

type User struct {
   
  gorm.Model
  CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

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

你也可以在删除记录时通过 Select 来删除 has many 关联的记录,查看 Delete with Select 获取详情

四 关联—Many To Many

4.1 Many To Many

Many to Many 会在两个 model 中添加一张连接表。

例如,您的应用包含了 user 和 language,且一个 user 可以说多种 language,多个 user 也可以说一种 language。

// User 拥有并属于多种 language,`user_languages` 是连接表
type User struct {
   
  gorm.Model
  Languages []Language `gorm:"many2many:user_languages;"`
}

type Language struct {
   
  gorm.Model
  Name string
}

当使用 GORM 的 AutoMigrateUser 创建表时,GORM 会自动创建连接表

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值