Gorm 是 Golang 的一个 orm 框架。ORM 是通过实例对象的语法,完成关系型 数据库的操作,是"对象-关系映射"(Object/Relational Mapping) 的缩写。使用 ORM 框架可以让我们更方便的操作数据库。
package main
import (
"fmt"
"gorm.io/driver/mysql" #mysql驱动
"gorm.io/gorm" #gorm
)
var (
db *gorm.DB
err error
)
func init() {
//sql日志
newLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{
SlowThreshold: time.Second,
LogLevel: logger.Info,
Colorful: true,
})
db, err = gorm.Open(mysql.Open("root:123456@tcp(127.0.0.1:3309)/test?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{Logger: newLogger})
if err != nil {
fmt.Println("connect database failed,err:", err)
return
}
}
Debug
#debug为logger.Info级别
db.Debug().Where("name = ?", "jinzhu").First(&User{})
// gorm.Model 的定义
type Model struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time //用于存储记录的创建时间
UpdatedAt time.Time //用于存储记录的修改时间
DeletedAt DeletedAt `gorm:"index"` //用于存储记录的删除时间
}
标签名 | 说明 |
---|---|
type | 数据类型:int uint varchar char |
column | 列名 |
default | 默认值 |
unique | 列唯一 |
size | 列大小 |
precision | 列精度 |
primaryKey | 主键 |
autoincrement | 自增 |
inde | 自增 |
uniqueIndex | 自增 |
check | 自增 |
<- | 写权限,<-:create创建,<-update更新,<-false没有写权限 |
-> | 读权限,->:false没有读权限 |
- | 忽略该字段 |
comment | 注释 |
not null | 不为空 |
标签名 | 说明 |
---|---|
MANY2MANY | 指定连接表 |
FOREIGNKEY | 设置外键 |
ASSOCIATION_FOREIGNKEY | 设置关联外键 |
POLYMORPHIC | 指定多态类型 |
POLYMORPHIC_VALUE | 指定多态值 |
JOINTABLE_FOREIGNKEY | 指定连接表的外键 |
ASSOCIATION_JOINTABLE_FOREIGNKEY | 指定连接表的关联外键 |
SAVE_ASSOCIATIONS | 是否自动完成 save 的相关操作 |
ASSOCIATION_AUTOUPDATE | 是否自动完成 update 的相关操作 |
ASSOCIATION_AUTOCREATE | 是否自动完成 create 的相关操作 |
ASSOCIATION_SAVE_REFERENCE | 是否自动完成引用的 save 的相关操作 |
PRELOAD | 是否自动完成预加载的相关操作 |
package main
import "fmt"
/*
老师和课程 一对一
课程和分数 一对一
学生和分数 一对多(分数)
学生和课程 多对多
*/
type Student struct {
ID int `gorm:"type:int"`
Sname string `gorm:"type:varchar(4);not null;comment '姓名'"`
Gender string `gorm:"type:char(4);default:'男';comment '性别'"`
Phone string `gorm:"char(11);not null;comment '手机号'"`
Course []Course `gorm:"many2many:StudentCourse"`
Grade []Grade `gorm:"ForeignKey:StudentId;AssociationForeignKey:ID;constraint:OnDelete:CASCADE"`
}
//默认情况表名为结构体名小写+s
//重写表名
func (table *Student) TableName() string {
return "student"
}
type Teacher struct {
ID int `gorm:"type:int"`
Tname string `gorm:"type:varchar(4);not null;comment '老师姓名'"`
Gender string `gorm:"type:char(4);default:'男';comment '性别'"`
Phone string `gorm:"char(11);not null;comment '手机号'"`
}
func (table *Teacher) TableName() string {
return "teacher"
}
type Course struct {
ID int `gorm:"type:int"`
Cname string `gorm:"type:varchar(10);not null;comment '课程名'"`
TeacherId int `gorm:"type:int;default:null;comment '老师id'"`
Teacher *Teacher `gorm:"ForeignKey:TeacherId;AssociationForeignKey:ID"` //is a 一对一关联
Student []Student `gorm:"many2many:StudentCourse"`
}
func (table *Course) TableName() string {
return "course"
}
type Grade struct {
ID int `gorm:"type:int"`
Score float64 `gorm:"type:float;default:0;comment '分数'"`
StudentId int `gorm:"type:int;default:null;comment '学生id'"`
CourseId int `gorm:"type:int;default:null;comment '课程id'"`
Course *Course `gorm:"ForeignKey:CourseId;AssociationForeignKey:ID;constraint"`
}
func (table *Grade) TableName() string {
return "grade"
}
func DataMigration() {
//迁移多张表
if err := db.AutoMigrate(&Teacher{}, &Student{}, &Course{}, &Grade{}); err != nil {
fmt.Println("数据迁移失败")
return
}
fmt.Println("数据迁移成功")
// 设置附加参数
db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&Teacher{}, &Student{}, &Course{}, &Grade{})
}
func InsertTeacher() {
//方法一
teacher := Teacher{
Tname: "张三",
Gender: "男",
Phone: "13333333333",
}
db.Create(&teacher)
//方法二
var teachers []Teacher
teacher1 := Teacher{
Tname: "李四",
Gender: "男",
Phone: "16666666666",
}
teacher2 := Teacher{
Tname: "王五",
Gender: "女",
Phone: "19999999999",
}
teachers = append(teachers, teacher1)
teachers = append(teachers, teacher2)
db.CreateInBatches(&teachers, 2)
}
func InsertCourse() {
//多对多表数据插入
course1 := Course{
Cname: "语文",
TeacherId: 1,
}
course2 := Course{
Cname: "数学",
TeacherId: 2,
}
course3 := Course{
Cname: "英语",
TeacherId: 3,
}
//第一次插入
db.Create(&[]Student{
{Sname: "小明", Gender: "男", Phone: "14444444444", Course: []Course{course1, course2, course3}},
})
course4 := Course{
ID: 1,
}
course5 := Course{
ID: 2,
}
db.Create(&Student{
Sname: "二明", Gender: "女", Phone: "16666666666", Course: []Course{course4, course5},
})
course6 := Course{
ID: 3,
}
//第二次插入
db.Create(&Student{
Sname: "大明", Gender: "男", Phone: "18888888888", Course: []Course{course6},
})
}
func InsertGrade() {
grades := []Grade{
{Score: 92, StudentId: 1, CourseId: 1},
{Score: 88, StudentId: 1, CourseId: 2},
{Score: 61, StudentId: 1, CourseId: 3},
{Score: 95, StudentId: 2, CourseId: 1},
{Score: 93, StudentId: 2, CourseId: 2},
{Score: 74, StudentId: 3, CourseId: 3},
}
db.NewRecord(grades ) // 主键为空返回`true`
db.Create(&grades)
db.NewRecord(grades ) // 创建`grades `后返回`false`
}
// 删除id=1的课程
course := Course{}
db.First(&course,1)
db.Delete(&course)
//删除学生id=1的分数
db.Where("student_id = ?", 1).Delete(Grade{})
student:= Student{}
db.First(&student)
student.Sname = "老大"
student.Gender = "女"
db.Save(&student)
// 更新单个属性,如果它有变化
db.Model(&student).Update("sname", "老二")
// 根据给定的条件更新单个属性
db.Model(&student).Where("id= ?", 3).Update("sname", "老三")
// 使用 map 更新多个属性,只会更新其中有变化的属性
db.Model(&student).Updates(map[string]interface{}{"sname": "老大", "gender": "女"})
// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
db.Model(&student).Updates(Student{Sname: "老大", Gender: "女"})
//只更新某些字段,这里只更新姓名不更新性别
db.Model(&student).Select("sname").Updates(map[string]interface{}{"sname": "老大","gender":"女"})
//不更新某些字段,这里只更新性别不更新姓名
db.Model(&student).Omit("sname").Updates(map[string]interface{}{"sname": "老大", "gender": "女"})
// 根据主键查询第一条数据
student := Student{}
db.First(&student )
// 随机获取一个数据
db.Take(&student )
// 根据查询最后一条数据
db.Last(&student )
// 查询指定id
db.First(&student , 10)
students := []Student{}
// 查询所有的数据
db.Find(&students )
// 查询匹配的一条数据
db.Where("sname = ?", "老大").First(&student)
// 查询匹配的所有数据
db.Where("sname = ?", "老大").Find(&students)
//不等于
db.Where("sname <> ?", "老大").Find(&students)
// in
db.Where("sname IN (?)", []string{"老大", "老二"}).Find(&students)
//like
db.Where("sname LIKE ?", "%老大%").Find(&students)
// and
db.Where("sname = ? AND gender = ?", "老大", "女").Find(&students)
// 时间
db.Where("updated_at > ?", lastWeek).Find(&students)
// between
grades := []Grades{}
db.Where("score BETWEEN ? AND ?", 60, 90).Find(&grades)
/*
老师和课程 一对一
课程和分数 一对一
学生和分数 一对多(分数)
学生和课程 多对多
*/
// 一对一查
// 查老师教的课程
func FindTeacherCourse() {
courses := []Course{}
db.Preload("Teacher").Find(&courses)
data, _ := json.Marshal(courses)
var m []map[string]interface{}
json.Unmarshal(data, &m)
fmt.Println(m)
}
// 一对多
// 学生对应的分数
func FindStudentGrade() {
students := []Student{}
db.Preload("Grades").Find(&students)
data, _ := json.Marshal(students)
var m []map[string]interface{}
json.Unmarshal(data, &m)
fmt.Println(m)
}
// 学生对应课程分数
type StudentCourseGrade struct {
Sname string `json:"sname"`
Cname string `json:"cname"`
Score int `json:"score"`
}
func FindStudentCourseGrade() {
student_course_grades := []StudentCourseGrade{}
// grades := []Grade{}
db.Debug().Table("grade").Joins("join student on student.id = grade.student_id").
Joins("join course on course.id = grade.course_id").
Select("student.sname,course.cname,grade.score").Scan(&student_course_grades)
fmt.Println(student_course_grades)
}
// 查大明对应的分数
func FindSomeoneGrade() {
student := Student{}
db.Where("sname = ?", "大明").First(&student)
grades := []Grade{}
db.Model(&student).Association("Grades").Find(&grades)
fmt.Println(grades)
}
// 多对多
// 学生对应的课程
func FindStudentCourse() {
students := []Student{}
db.Preload("Course").Find(&students)
fmt.Println(students)
}