【gin学习笔记】08gorm结构体的创建和结合gin的使用

本文学习视频 https://www.bilibili.com/video/BV1kC4y1t7Qi/?spm_id_from=333.788

tag设置

  • 设置主键: gorm:“primary_key”
  • 自定义字段名称: column:user_id
  • 忽略: “-”
  • 指定数据类型t:ype:varchar(100)
  • 非空:not null
  • 创建索引: index
  • 设置外键:ForeignKey
  • 关联外键:AssociationForeignKey
  • 多对多:many2many:表面

自定义表名

一般如果不指定的话,表名就是结构体的名字,如果想自定义表表名要用到TableName()这个方法

tag设置和自定义表名的代码如下:

package main

import (
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
)

type User struct {
	gorm.Model
	//设置主键,字段名称设置为user_name,字段类型设置为varchar长度为100
	Name string `gorm:"primary_key;column:user_name;type:varchar(100)"`
	Age  int
}

//将表名设置为my_users
func (u User) TableName() string {
	return "my_users"
}

func main() {
	db, _ := gorm.Open("mysql",
		"root:root@/ginclass?charset=utf8mb4&parseTime=True&loc=Local")
	defer db.Close()
	db.AutoMigrate(&User{})
}

运行后创建出来的表结构如下:
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第1张图片

重点:结构体声明 1对1 1对多 多对多

  • 多对多使用many2many关键字
  • 分页查询使用count记录总数,使用limit和offset指定记录位置
  • 预加载 preload

举例:
一对一 一个学生有一个身份证
一对多 一个学生有一个班级,一个班级有多个学生
多对多 一个学生有多个老师 一个老师有多个学生

下面举例来创建一些表并生成一些数据

package main

import (
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
)

//一对一:学生每个人有一张IDCard,IDCard通过ID来知道是哪个学生的,这是一对一关系
//一对多:班级有多个学生,学生通过ClassID知道自己在哪个班
//多对多:老师有多个学生,并且知道学生的ID;学生有多个老师,并且知道老师的ID

type Class struct {
	gorm.Model
	ClassName string
	Students  []Student //一个班级有多个学生
}

type Student struct {
	gorm.Model
	StudentName string
	ClassID     uint      //每个学生都有一个班级
	IDCard      IDCard    //每个学生都有一张IDCard
	Teachers    []Teacher `gorm:"many2many:student_teachers;"` //一个学生有多个老师 student_teachers是关联表
}

type Teacher struct {
	gorm.Model
	TeacherName string
	StudentID   uint
	Students    []Student `gorm:"many2many:student_teachers;"` //一个老师有多个学生
}

type IDCard struct {
	gorm.Model
	StudentID uint //每个学生有一个IDcard 与学生的ID进行关联
	Num       int
}

func main() {
	db, _ := gorm.Open("mysql",
		"root:root@/ginclass?charset=utf8mb4&parseTime=True&loc=Local")
	defer db.Close()
	
	//创建Teacher表,Class表,Student表,IDCard表,还有之前的关联表student_teachers
	db.AutoMigrate(&Teacher{}, &Class{}, &Student{}, &IDCard{})
	
	i := IDCard{
		Num: 123456,
	}
	//创建一个学生
	s := Student{
		StudentName: "kaka",
		IDCard:      i,
	}
	//创建一个老师
	t := Teacher{
		TeacherName: "张老师",
	}
	//创建一个班级
	c := Class{
		ClassName: "文科班",
		Students:  []Student{s},
	}
	_ = db.Create(&c).Error //把班级信息写到数据库
	_ = db.Create(&t).Error //把老师信息写到数据库
}

运行后会在数据库中看到如下信息:
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第2张图片
class表中创建了一条名字为文科班的数据,id为1
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第3张图片
学生表中创建了一条学生名字为kaka的数据,班级id为1,学生id为1
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第4张图片
IDCard表中创建了一条卡号为123456的数据
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第5张图片
teacher表中也相应创建了一条数据
但是many2many关联表student_teachers里面没有数据,这里面的数据怎么创建呢?
代码如下,只需要在teacher中加入Students: []Student{s} 即可

//创建一个老师
	t := Teacher{
		TeacherName: "张老师",
		Students:    []Student{s},
	}

运行后结果如下
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第6张图片
创建了id为2的老师数据

【gin学习笔记】08gorm结构体的创建和结合gin的使用_第7张图片
创建了id为3的student数据
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第8张图片
teacher 2 和student 3对应上了

使用gin接受参数并经过处理入库或返回

我们创建一个/student路由

package main

import (
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
)

//一对一:学生每个人有一张IDCard,IDCard通过ID来知道是哪个学生的,这是一对一关系
//一对多:班级有多个学生,学生通过ClassID知道自己在哪个班
//多对多:老师有多个学生,并且知道学生的ID;学生有多个老师,并且知道老师的ID

type Class struct {
	gorm.Model
	ClassName string
	Students  []Student //一个班级有多个学生
}

type Student struct {
	gorm.Model
	StudentName string
	ClassID     uint      //每个学生都有一个班级
	IDCard      IDCard    //每个学生都有一张IDCard
	Teachers    []Teacher `gorm:"many2many:student_teachers;"` //一个学生有多个老师 student_teachers是关联表
}

type Teacher struct {
	gorm.Model
	TeacherName string
	StudentID   uint
	Students    []Student `gorm:"many2many:student_teachers;"` //一个老师有多个学生
}

type IDCard struct {
	gorm.Model
	StudentID uint //每个学生有一个IDcard 与学生的ID进行关联
	Num       int
}

func main() {
	db, _ := gorm.Open("mysql",
		"ginclass:Fjj@sh123@/ginclass?charset=utf8mb4&parseTime=True&loc=Local")
	defer db.Close()

	r := gin.Default()
	r.POST("/student", func(c *gin.Context) {
		var student Student
		_ = c.BindJSON(&student)
		db.Create(&student)
	})
	r.Run(":8888")
}

【gin学习笔记】08gorm结构体的创建和结合gin的使用_第9张图片
post请求的header中加上 Content-Type applicaiton/json,用来告诉服务端消息主体是序列化后的 JSON 字符串。

Body中传入以上信息,运行后数据正常入库。【gin学习笔记】08gorm结构体的创建和结合gin的使用_第10张图片
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第11张图片
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第12张图片
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第13张图片

用gin路由查询数据库里的数据

创建一个get路由

package main

import (
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
)

//一对一:学生每个人有一张IDCard,IDCard通过ID来知道是哪个学生的,这是一对一关系
//一对多:班级有多个学生,学生通过ClassID知道自己在哪个班
//多对多:老师有多个学生,并且知道学生的ID;学生有多个老师,并且知道老师的ID

type Class struct {
	gorm.Model
	ClassName string
	Students  []Student //一个班级有多个学生
}

type Student struct {
	gorm.Model
	StudentName string
	ClassID     uint      //每个学生都有一个班级
	IDCard      IDCard    //每个学生都有一张IDCard
	Teachers    []Teacher `gorm:"many2many:student_teachers;"` //一个学生有多个老师 student_teachers是关联表
}

type Teacher struct {
	gorm.Model
	TeacherName string
	StudentID   uint
	Students    []Student `gorm:"many2many:student_teachers;"` //一个老师有多个学生
}

type IDCard struct {
	gorm.Model
	StudentID uint //每个学生有一个IDcard 与学生的ID进行关联
	Num       int
}

func main() {
	db, _ := gorm.Open("mysql",
		"ginclass:Fjj@sh123@/ginclass?charset=utf8mb4&parseTime=True&loc=Local")
	defer db.Close()

	r := gin.Default()
	r.POST("/student", func(c *gin.Context) {
		var student Student
		_ = c.BindJSON(&student)
		db.Create(&student)
	})

	r.GET("/student/:ID", func(c *gin.Context) {
		id := c.Param("ID") //从前端拿到ID,并赋给id
		var student Student
		db.First(&student, "id=?", id) //通过id去数据库里查询一条数据并把结果返回给student
		//将student返回前端
		c.JSON(200, gin.H{
			"学生信息": student,
		})
	})

	r.Run(":8888")
}

【gin学习笔记】08gorm结构体的创建和结合gin的使用_第14张图片
查询id为2的学生信息,可以看到返回的只有基础信息,其他的信息都没返回。为了将其他信息也查出来就需要preload

db.Preload("Teachers").Preload("IDCard").First(&student, "id=?", id) //通过id去数据库里查询一条数据并把结果返回给student
		//将student返回前端

db.First前面加Preload
重新get下会发现返回的信息变多了,结果如下:

{
    "学生信息": {
        "ID": 2,
        "CreatedAt": "2022-05-12T23:35:38+08:00",
        "UpdatedAt": "2022-05-12T23:35:38+08:00",
        "DeletedAt": null,
        "StudentName": "Jack",
        "ClassID": 1,
        "IDCard": {
            "ID": 4,
            "CreatedAt": "2022-05-12T23:35:38+08:00",
            "UpdatedAt": "2022-05-12T23:35:38+08:00",
            "DeletedAt": null,
            "StudentID": 2,
            "Num": 666666
        },
        "Teachers": [
            {
                "ID": 3,
                "CreatedAt": "2022-05-12T23:35:38+08:00",
                "UpdatedAt": "2022-05-12T23:35:38+08:00",
                "DeletedAt": null,
                "TeacherName": "语文老师",
                "StudentID": 0,
                "Students": null
            },
            {
                "ID": 4,
                "CreatedAt": "2022-05-12T23:35:38+08:00",
                "UpdatedAt": "2022-05-12T23:35:38+08:00",
                "DeletedAt": null,
                "TeacherName": "英语老师",
                "StudentID": 0,
                "Students": null
            }
        ]
    }
}

接下来通过class把students都查出来

r.GET("/class/:ID", func(c *gin.Context) {
		id := c.Param("ID") //从前端拿到ID,并赋给id
		var class Class
		db.First(&class, "id=?", id) //通过id去数据库里查询一条数据并把结果返回给class
		//将class返回前端
		c.JSON(200, gin.H{
			"班级信息": class,
		})
	})

查询后返回结果如下
【gin学习笔记】08gorm结构体的创建和结合gin的使用_第15张图片
可以看到没有Students信息,接下来我们通过preload将students信息查询出来。

r.GET("/class/:ID", func(c *gin.Context) {
		id := c.Param("ID") //从前端拿到ID,并赋给id
		var class Class
		db.Preload("Students").First(&class, "id=?", id) //通过id去数据库里查询一条数据并把结果返回给class
		//将class返回前端
		c.JSON(200, gin.H{
			"班级信息": class,
		})
	})

结果如下

{
    "班级信息": {
        "ID": 1,
        "CreatedAt": "2022-05-12T22:06:51+08:00",
        "UpdatedAt": "2022-05-12T22:06:51+08:00",
        "DeletedAt": null,
        "ClassName": "文科班",
        "Students": [
            {
                "ID": 2,
                "CreatedAt": "2022-05-12T23:35:38+08:00",
                "UpdatedAt": "2022-05-12T23:35:38+08:00",
                "DeletedAt": null,
                "StudentName": "Jack",
                "ClassID": 1,
                "IDCard": {
                    "ID": 0,
                    "CreatedAt": "0001-01-01T00:00:00Z",
                    "UpdatedAt": "0001-01-01T00:00:00Z",
                    "DeletedAt": null,
                    "StudentID": 0,
                    "Num": 0
                },
                "Teachers": null
            }
        ]
    }
}

可以看到students信息确实出来了,但是student关联的信息没有查出来。
这个就涉及到嵌套预加载的问题。

r.GET("/class/:ID", func(c *gin.Context) {
		id := c.Param("ID") //从前端拿到ID,并赋给id
		var class Class
		db.Preload("Students").Preload("Students.IDCard").Preload("Students.Teachers").First(&class, "id=?", id) //通过id去数据库里查询一条数据并把结果返回给class
		//将class返回前端
		c.JSON(200, gin.H{
			"班级信息": class,
		})
	})

嵌套了Students.IDCard, Students.Teachers
返回结果如下

{
    "班级信息": {
        "ID": 1,
        "CreatedAt": "2022-05-12T22:06:51+08:00",
        "UpdatedAt": "2022-05-12T22:06:51+08:00",
        "DeletedAt": null,
        "ClassName": "文科班",
        "Students": [
            {
                "ID": 2,
                "CreatedAt": "2022-05-12T23:35:38+08:00",
                "UpdatedAt": "2022-05-12T23:35:38+08:00",
                "DeletedAt": null,
                "StudentName": "Jack",
                "ClassID": 1,
                "IDCard": {
                    "ID": 4,
                    "CreatedAt": "2022-05-12T23:35:38+08:00",
                    "UpdatedAt": "2022-05-12T23:35:38+08:00",
                    "DeletedAt": null,
                    "StudentID": 2,
                    "Num": 666666
                },
                "Teachers": [
                    {
                        "ID": 3,
                        "CreatedAt": "2022-05-12T23:35:38+08:00",
                        "UpdatedAt": "2022-05-12T23:35:38+08:00",
                        "DeletedAt": null,
                        "TeacherName": "语文老师",
                        "StudentID": 0,
                        "Students": null
                    },
                    {
                        "ID": 4,
                        "CreatedAt": "2022-05-12T23:35:38+08:00",
                        "UpdatedAt": "2022-05-12T23:35:38+08:00",
                        "DeletedAt": null,
                        "TeacherName": "英语老师",
                        "StudentID": 0,
                        "Students": null
                    }
                ]
            }
        ]
    }
}

其他的gorm操作可以参考https://learnku.com/docs/gorm/v2

你可能感兴趣的:(golang,gin,学习,golang,数据库)