转自:https://www.dazhuanlan.com/2019/09/24/5d895f182bfbe/
1.多对多关系的定义
type Student struct {
gorm.Model
Code string
Name string
Books []Book `gorm:"many2many:student_books;"`
}
type Book struct {
gorm.Model
Name string
Students []Student `gorm:"many2many:student_books;"`
}
注意:我刚开始加了json相关的信息,这个联结表就没有生成( json: "books" gorm:"many2many:student_books;"
)
切记gorm:跟many2many之间不能有空格,否则联结表不会生成。定义了模型以后,只要调用db.AutoMigrate(&Student{}, &Book{})会生成三张表。
mysql> show tables;
+-----------------------------------+
| Tables_in_gorm |
+-----------------------------------+
| books |
| student_books |
| students |
+-----------------------------------+
2.多对多数据的插入
有两种方式:
2.1 直接在数据定义的时候指定。
student3 := Student{Code: "000003", Name: "王五" }
db.Save(&student3)
book2 := Book{
Name: "神雕侠侣", Students: []Student {
student3,
},
}
这里需要注意,指定的数据必须是数据库有的数据,也就是保存过,或者查找出来的数据结构。如果按照下面这样的写法:
book2 := Book{
Name: "神雕侠侣", Students: []Student {
{Code: "000003", Name: "王五" },
},
}
将会在student表中创建一个新项目,并不会用数据库已有的数据来建立联结。
所以下面这样插入也是可以的。
var studentlist []Student
db.Table("students").Where("id = 1").Or("id = 2").Find(&studentlist)
book1 := Book{Name: "笑傲江湖", Students: studentlist}
2.2 使用关联模式的append插入
1
db.Model(&bookQ).Association("Students").Append(Student{Code: "000005", Name: "西门吹雪"})
这里面也有个坑,在下面我再介绍。
经过上面这样数据插入以后,联结表的关系会自动的创建出来。
3.关联模式
关联模式最大的坑跟上面一样,就是Model的参数,必须是数据库里的数据,否则就是crash
当表建立完成以后,我们要操作的某一个项目的联系,可以像下面这样:
var bookQ Book
db.Table("books").Where("id = 1").First(&bookQ)
db.Model(&bookQ).Association("Students").Find(&studentlist)
这样所有第一本书借阅的同学都出来了。
要增加一个同学给这本书
db.Model(&bookQ).Association("Students").Append(student3)
这里也要记得student3必须是数据库保存,或者查找的数据。
删除某个关系
db.Model(&bookQ).Association("Students").Delete(student3)
完整的代码如下:
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"fmt"
)
type Student struct {
gorm.Model
Code string
Name string
Books []Book `gorm:"many2many:student_books;"`
}
type Book struct {
gorm.Model
Name string
Students []Student `gorm:"many2many:student_books;"`
}
func main() {
db := Connect()
defer db.Close()
db.LogMode(true)
purgeDB(db)
db.AutoMigrate(&Student{}, &Book{})
student1 := Student{Code: "000001", Name: "张三"}
student2 := Student{Code: "000002", Name: "李四"}
student3 := Student{Code: "000003", Name: "王五" }
db.Save(&student1)
db.Save(&student2)
db.Save(&student3)
var studentlist []Student
db.Table("students").Where("id = 1").Or("id = 2").Find(&studentlist)
book1 := Book{Name: "笑傲江湖", Students: studentlist}
book2 := Book{
Name: "神雕侠侣", Students: []Student {
student3,
},
}
db.Save(&book1)
db.Save(&book2)
var student Student
db.Table("students").Where("id = 1").First(&student)
book := []Book{}
db.Preload("Students").Find(&book)
fmt.Println(book)
db.Model(&student).Related(&book, "Books")
fmt.Println(book)
db.Model(&student).Association("Books").Find(&book)
fmt.Println(book)
var bookQ Book
db.Table("books").Where("id = 1").First(&bookQ)
db.Model(&bookQ).Association("Students").Find(&studentlist)
fmt.Println(studentlist)
db.Model(&bookQ).Association("Students").Append(student3)
db.Model(&bookQ).Association("Students").Append(Student{Code: "000005", Name: "西门吹雪"})
db.Model(&bookQ).Association("Students").Delete(student3)
db.Model(&bookQ).Association("Students").Clear()
}
func purgeDB(db *gorm.DB) {
if db.HasTable(&Student{}) {
db.DropTable(&Student{})
}
if db.HasTable(&Book{}) {
db.DropTable(&Book{})
}
}