关联之多对多
一个女神可以有多个狗哥,一个狗哥也可以有多个女神
Go
type M2MWallet struct {
ID uint
Amount float64
M2MDogID uint // 外键,就是M2MDog.ID
}
type M2MDog struct {
ID uint
Name string
M2MGirlGods []M2MGirlGod `gorm:"many2many:dog_girl_god"` // 一个狗哥可以关联多个女神
M2MWallet M2MWallet
}
type M2MGirlGod struct {
ID uint
Name string
M2MDogs []M2MDog `gorm:"many2many:dog_girl_god"` // 一个女神可以关联多个狗哥
}
自动迁移
Go
func autoMigrate() {
DB.AutoMigrate(&M2MDog{}, &M2MGirlGod{}, &M2MWallet{})
}
执行上面代码会创建4个表,除了上面声明的3个表,会额外创建
dog_girl_god
表(通过声明的gorm:"many2many:dog_girl_god"
tag自动生成的),该表记录了M2MDog
和M2MGirlGod
之间的关联关系
SQL
CREATE TABLE dog_girl_god
(
m2_m_girl_god_id bigint UNSIGNED NOT NULL,
m2_m_dog_id bigint UNSIGNED NOT NULL,
PRIMARY KEY (m2_m_girl_god_id, m2_m_dog_id),
CONSTRAINT fk_dog_girl_god_m2_m_dog
FOREIGN KEY (m2_m_dog_id) REFERENCES m2_m_dogs (id),
CONSTRAINT fk_dog_girl_god_m2_m_girl_god
FOREIGN KEY (m2_m_girl_god_id) REFERENCES m2_m_girl_gods (id)
);
准备数据
Go
// 创建几个狗哥
func createM2MData() {
d1 := M2MDog{Name: "狗哥1号"}
d2 := M2MDog{Name: "狗哥2号"}
d3 := M2MDog{Name: "狗哥3号"}
d4 := M2MDog{Name: "狗哥4号"}
d5 := M2MDog{Name: "狗哥5号"}
d6 := M2MDog{Name: "狗哥6号"}
dogs := []M2MDog{d1, d2, d3, d4, d5, d6}
DB.Model(&M2MDog{}).Create(&dogs)
}
// 创建女神并关联狗哥
func girl2DogAssociation() {
// 狗哥1号
var d1 M2MDog
DB.Model(&M2MDog{}).Find(&d1, 1)
// 创建女神1号 并将其和狗哥1号关联
//g1 := M2MGirlGod{Name: "女神1号"}
//DB.Model(&d1).Association("M2MGirlGods").Append(&g1)
// 创建女神2号 并将其和狗哥1号关联
//g2 := M2MGirlGod{Name: "女神2号"}
//DB.Model(&d1).Association("M2MGirlGods").Append(&g2)
// 创建女神3、4号 并将其和狗哥1号关联
g3 := M2MGirlGod{Name: "女神3号"}
g4 := M2MGirlGod{Name: "女神4号"}
DB.Model(&d1).Association("M2MGirlGods").Append(&g3, &g4)
}
准备
M2MWallet
数据
json
[
{
"id": 1,
"amount": 10000,
"m2_m_dog_id": 1
},
{
"id": 2,
"amount": 80000,
"m2_m_dog_id": 2
},
{
"id": 3,
"amount": 6000,
"m2_m_dog_id": 3
}
]
修改
dog_girl_god
表
狗哥1号
关联了女神1、2、3、4
号
女神一号
关联了狗哥1、2、3
号
json
[
{
"m2_m_girl_god_id": 1,
"m2_m_dog_id": 1
},
{
"m2_m_girl_god_id": 2,
"m2_m_dog_id": 1
},
{
"m2_m_girl_god_id": 3,
"m2_m_dog_id": 1
},
{
"m2_m_girl_god_id": 4,
"m2_m_dog_id": 1
},
{
"m2_m_girl_god_id": 1,
"m2_m_dog_id": 2
},
{
"m2_m_girl_god_id": 1,
"m2_m_dog_id": 3
}
]
增删改
和之前的一对一
、一对多
的差不多
查询
查询
女神1号
关联的狗哥的数据,带上狗哥的小金库信息
Go
func queryGirl() {
// 查出女神1号
var g1 M2MGirlGod
DB.Model(&M2MGirlGod{}).Find(&g1, 1)
var dogs []M2MDog
// 查询女神1号关联的狗哥
DB.Model(&g1).Preload("M2MWallet").Association("M2MDogs").Find(&dogs)
// 女神1号关联的狗哥 => [{1 狗哥1号 [] {1 10000 1}} {2 狗哥2号 [] {2 80000 2}} {3 狗哥3号 [] {3 6000 3}}]
fmt.Printf("女神1号关联的狗哥 => %v\n", dogs)
}
查询
女神1号
关联的狗哥的数据,带上狗哥的小金库
信息,并带出狗哥的女神
的信息
Go
func queryGirl() {
// 查出女神1号
var g1 M2MGirlGod
DB.Model(&M2MGirlGod{}).Find(&g1, 1)
var dogs []M2MDog
// 查询女神1号关联的狗哥
//DB.Model(&g1).Preload("M2MWallet").Association("M2MDogs").Find(&dogs)
DB.Model(&g1).Preload("M2MWallet").Preload("M2MGirlGods").Association("M2MDogs").Find(&dogs)
/**
女神1号关联的狗哥 => [{1 狗哥1号 [{1 女神1号 []} {2 女神2号 []} {3 女神3号 []} {4 女神4号 []}] {1 10000 1}} {2 狗哥2号 [{1 女神1号 []}] {2 80000 2}} {3 狗哥3号 [{1 女神1号 []}]
*/
fmt.Printf("女神1号关联的狗哥 => %v\n", dogs)
}
查询
女神1号
关联的狗哥的数据,带上狗哥的小金库
信息,并且要余额大于等于10000
的
Go
func queryByJoin() {
// 查出女神1号
var g1 M2MGirlGod
DB.Model(&M2MGirlGod{}).Find(&g1, 1)
var dogs []M2MDog
DB.Model(&M2MDog{})
.Preload("M2MWallet")
.Joins("JOIN dog_girl_god dg ON dg.m2_m_dog_id = m2_m_dogs.id")
.Joins("JOIN m2_m_wallets w on w.m2_m_dog_id = m2_m_dogs.id")
.Where("dg.m2_m_girl_god_id = ?", g1.ID)
.Where("w.amount >= ?", 10000)
.Find(&dogs)
// 女神1号关联的狗哥 => [{1 狗哥1号 [] {1 10000 1}} {2 狗哥2号 [] {2 80000 2}}]
fmt.Printf("女神1号关联的狗哥 => %v\n", dogs)
}
上述代码执行的
SQL
如下
SQL
SELECT `m2_m_dogs`.`id`,`m2_m_dogs`.`name` FROM `m2_m_dogs`
JOIN dog_girl_god dg ON dg.m2_m_dog_id = m2_m_dogs.id
JOIN m2_m_wallets w on w.m2_m_dog_id = m2_m_dogs.id
WHERE dg.m2_m_girl_god_id = 1 AND w.amount >= 100001