说人话的 GORM文档 之多态关联

24 min read

GORM 那傻逼文档真是傻逼妈妈给傻逼儿子开门,傻逼到家了

GORM 的多态关联支持允许你在 Go 语言中实现类似于多态的功能。在这个例子中,我们有两个拥有者实体:CatDog,它们都可以拥有一个 Toy。通过使用 GORM 的多态关联特性,我们可以轻松地在不同类型的拥有者之间共享这个 Toy 结构。这使得在不同类型的实体之间共享相同的子实体变得简单且灵活。

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

当你使用多态关联时,GORM 会在拥有者实体(如 CatDog)中创建一个字段,该字段将引用与之关联的 Toy 结构。在这个例子中,Toy 结构的 OwnerID 字段保存了拥有者实体的主键值,而 OwnerType 字段保存了拥有者实体的表名。这使得 GORM 可以轻松地找到关联的拥有者实体。

以下是多态关联的一个使用场景:

假设你正在开发一个宠物商店的应用程序,商店里有许多不同类型的宠物,如猫、狗等。商店还提供各种玩具供宠物玩耍。在这种情况下,你可以使用多态关联来表示这种关系。这样,你就可以通过查询 Toy 结构来获取与特定玩具关联的宠物,而不必为每种宠物类型创建单独的 Toy 结构。

下面是一个示例查询,展示了如何使用多态关联获取与特定玩具关联的宠物:

var toy Toy
db.Preload("Owner").Find(&toy, "id = ?", 1)

这个查询将预加载与 toy 关联的宠物(无论是猫还是狗)。你可以使用 toy.Owner 来访问它们。通过使用多态关联,你可以方便地处理各种宠物类型及其关联的玩具,而无需为每个类型创建冗余的结构和查询。

上面在数据库的表结构展示如下:

在这个例子中,我们有3个数据表:catsdogstoys。以下是这些表的结构和示例值:

  1. cats 表:
字段名 字段类型 示例值
ID int 1
Name string "cat1"
  1. dogs 表:
字段名 字段类型 示例值
ID int 1
Name string "dog1"
  1. toys 表:
字段名 字段类型 示例值
ID int 1
Name string "toy1"
OwnerID int 1
OwnerType string "dogs"

示例值表示:

  • cats 表中有一只名为 "cat1" 的猫。
  • dogs 表中有一只名为 "dog1" 的狗。
  • toys 表中有一件名为 "toy1" 的玩具,该玩具的所有者(Owner)是 ID 为 1 的狗。

注意,toys 表中的 OwnerType 字段值是拥有者实体的表名。在这个例子中,OwnerType 的值是 "dogs",表示这个玩具属于一只狗。同样,如果玩具属于一只猫,OwnerType 的值将是 "cats"。

  • Toys 表与两张表关联, Cat和Dog 里面指定关联键
  • 以Cat为例子,在Cat定义关联表Toys,声明polymorphic[关联键] ,那么表记录与另两张表的关联内容,[关联键]ID 为 Cat的id, [关联键]Type 为Cat的表名