GORM学习笔记
1、数据准备
# 班级表
create table class(
id int primary key auto_increment,
name varchar(20),
description varchar(100)
);
# 学生表
create table student(
id int primary key auto_increment,
sn varchar(20),
name varchar(20),
email varchar(20),
class_id int,
monitor_id int,
constraint student_class_id foreign key (class_id) references class(id),
constraint student_monitor_id foreign key (monitor_id) references student(id)
);
# 课程表
create table course(
id int primary key auto_increment,
name varchar(20)
);
# 选课表
create table selection(
student_id int,
course_id int,
constraint score_student_id foreign key (student_id) references student(id),
constraint score_course_id foreign key (course_id) references course(id)
);
2、快速开始
2.1、安装依赖
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
2.2、db
package model
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
var err error
func init() {
dsn := "root:Chace2233.@tcp(127.0.0.1:3306)/study?charset=utf8&parseTime=True&loc=Local"
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
}
fmt.Println(DB)
}
2.3、bean
package bean
type Student struct {
Id int
Sn string
Name string
Email string
ClassId
MonitorId int
}
func (s Student) TableName() string {
return "student"
}
2.4、controller
package controller
import (
"fmt"
"ginstudy/model"
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
type StudentController struct {}
func (student StudentController) Select(c *gin.Context) {
var users []model.Student
// 全量查询
//model.DB.Find(&users)
// 条件查询
model.DB.Where("id<6").Find(&users)
c.JSON(http.StatusOK, users)
}
func (student StudentController) Insert(c *gin.Context) {
var user = model.Student{Sn: "10019", Name: "aaa", Email: "[email protected]", ClassId: 1, MonitorId: 1}
tx := model.DB.Create(&user)
fmt.Println(tx.Error)
if tx.Error != nil {
c.JSON(http.StatusOK, gin.H{
"insert": "error",
"message": tx.Error,
})
} else {
c.JSON(http.StatusOK, gin.H{
"insert": "success",
})
}
}
func (student StudentController) Update(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
// 修改方式1
//var user = model.Student{Id: id}
//model.DB.Find(&user)
//user.Name = "5A+"
//tx := model.DB.Save(&user)
//if tx.Error != nil {
// c.JSON(http.StatusOK, gin.H{
// "update": "error",
// "message": tx.Error,
// })
//} else {
// c.JSON(http.StatusOK, gin.H{
// "update": "success",
// })
//}
// 修改方式2
tx := model.DB.Model(&model.Student{}).Where("id=?", id).Update("name", "gorm")
if tx.Error != nil {
c.JSON(http.StatusOK, gin.H{
"update": "error",
"message": tx.Error,
})
} else {
c.JSON(http.StatusOK, gin.H{
"update": "success",
})
}
}
func (student StudentController) Delete(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
var user = model.Student{Id: id}
tx := model.DB.Delete(&user)
if tx.Error != nil {
c.JSON(http.StatusOK, gin.H{
"delete": "error",
"message": tx.Error,
})
} else {
c.JSON(http.StatusOK, gin.H{
"delete": "success",
})
}
}
2.5、router
package router
import (
"ginstudy/controller"
"github.com/gin-gonic/gin"
)
func StudentRouter(r *gin.Engine) {
group := r.Group("/student")
studentController := controller.StudentController{}
{
group.GET("/", studentController.Select)
group.POST("/insert", studentController.Insert)
group.PUT("/update/:id", studentController.Update)
group.DELETE("/delete/:id", studentController.Delete)
}
}
3、单表查询
3.1、字段别名
type Student struct {
Id int `json:"id"`
Sn string `json:"sn"`
Name string `json:"name"`
Email string `json:"email"`
ClassId int `json:"class-id"`
MonitorId int `json:"monitor-id"`
}
3.2、条件查询
func (student StudentController) Select(c *gin.Context) {
var users []model.Student
// 全量查询
//model.DB.Find(&users)
// 条件查询1
//model.DB.Where("id<6").Find(&users)
//model.DB.Where("id<?", 6).Find(&users)
// 条件查询2
//model.DB.Where("id>1 and id<5").Find(&users)
//model.DB.Where("id>? and id<=?", 1, 5).Find(&users)
// 条件查询3
//model.DB.Where("id in (?)", []int{1, 5}).Find(&users)
// 条件查询4
//model.DB.Where("name like ?", "%zhou%").Find(&users)
// 条件查询5
//model.DB.Where("id between ? and ?", 1, 3).Find(&users)
// 条件查询6
//model.DB.Where("id = ? or id = ?", 1, 3).Find(&users)
model.DB.Where("id = ? or id = ?", 1, 3).Or("id = ?", 5).Find(&users)
c.JSON(http.StatusOK, users)
}
3.3、指定字段
其他字段置空,可自定义结构体(注意指定表名)
func (student StudentController) Select(c *gin.Context) {
var users []model.Student
// 全量查询
model.DB.Select("id,name").Find(&users)
c.JSON(http.StatusOK, users)
}
3.4、排序
func (student StudentController) Select(c *gin.Context) {
var users []model.Student
// 全量查询
model.DB.Order("id desc").Find(&users)
c.JSON(http.StatusOK, users)
}
3.5、分页查询
func (student StudentController) Select(c *gin.Context) {
var users []model.Student
// 全量查询
model.DB.Order("id desc").Offset(3).Limit(2).Find(&users)
c.JSON(http.StatusOK, users)
}
3.6、计数
func (student StudentController) Select(c *gin.Context) {
var users []model.Student
// 全量查询
var count int64
model.DB.Find(&users).Count(&count)
fmt.Println(count)
c.JSON(http.StatusOK, users)
}
4、原生SQL
4.1、原生插入
func (student StudentController) Exec(c *gin.Context) {
model.DB.Exec("INSERT INTO student (sn, name, email, class_id, monitor_id) VALUES ('10020', 'ceshi', '[email protected]', 1, 2)")
c.JSON(http.StatusOK, gin.H{
"status": "success",
})
}
4.2、原生修改
func (student StudentController) Exec(c *gin.Context) {
model.DB.Exec("update student set name=? where sn=?", "gorm", 10019)
c.JSON(http.StatusOK, gin.H{
"status": "success",
})
}
4.3、原生删除
func (student StudentController) Exec(c *gin.Context) {
model.DB.Exec("delete from student where sn=?", 10019)
c.JSON(http.StatusOK, gin.H{
"status": "success",
})
}
4.3、原生查询
func (student StudentController) Exec(c *gin.Context) {
var users []model.Student
model.DB.Raw("select * from student").Scan(&users)
c.JSON(http.StatusOK, gin.H{
"status": "success",
"data": users,
})
}
5、多表查询
5.1、一对一
1、bean
package bean
type Student struct {
Id int
Sn string
Name string
Email string
// column指定当前表中的字段名,references指定关联表中的字段名
ClassId int `gorm:"column:class_id;references:id"`
MonitorId int
// 指定外键(注意是外键)
Class Class `gorm:"foreignKey:ClassId"`
}
func (s Student) TableName() string {
return "student"
}
package bean
type Class struct {
Id int
Name string
Description string
}
func (c Class) TableName() string {
return "class"
}
2、controller
package controller
import (
"fmt"
"github.com/gin-gonic/gin"
"gormstudy/bean"
"gormstudy/model"
"net/http"
"strconv"
)
type StudentController struct{}
func (student StudentController) Select(c *gin.Context) {
var users []bean.Student
model.DB.Preload("Class").Find(&users)
c.JSON(http.StatusOK, users)
}
5.2、一对多
1、bean
package bean
type Class struct {
// column指定当前表中的字段名,references指定关联表中的字段名
Id int `gorm:"column:id;references:class_id"`
Name string
Description string
// 指定外键(注意是外键)
Students []Student `gorm:"foreignKey:ClassId"`
}
func (c Class) TableName() string {
return "class"
}
type Student struct {
Id int
Sn string
Name string
Email string
ClassId int
MonitorId int
}
func (s Student) TableName() string {
return "student"
}
2、controller
package controller
import (
"github.com/gin-gonic/gin"
"gormstudy/bean"
"gormstudy/model"
"net/http"
)
type ClassController struct{}
func (class ClassController) Select(c *gin.Context) {
var classes []bean.Class
model.DB.Preload("Students").Find(&classes)
c.JSON(http.StatusOK, classes)
}
5.5、多对多
1、bean
package bean
type Course struct {
Id int `json:"id"`
Name string `json:"name"`
Students []Student `gorm:"many2many:selection;"`
}
func (s Course) TableName() string {
return "course"
}
2、controller
package controller
import (
"ginstudy/bean"
"ginstudy/model"
"github.com/gin-gonic/gin"
"net/http"
)
type CourseController struct{}
func (course CourseController) Select(c *gin.Context) {
var courses []bean.Course
// 查询所有课程的学生选修情况
// model.DB.Preload("Students").Find(&courses)
// 查询 JAVA 课程的学生选修情况
model.DB.Preload("Students").Where("name=?", "JAVA").Find(&courses)
c.JSON(http.StatusOK, courses)
}
6、预加载SQL
6.1、添加条件
func (course CourseController) Select(c *gin.Context) {
var courses []bean.Course
// 查询 JAVA 课程的学生选修情况(排除学生姓名为 xumeng03 的)
model.DB.Preload("Students", "name!=?", "xumeng03").Where("name=?", "JAVA").Find(&courses)
c.JSON(http.StatusOK, courses)
}
6.2、自定义
func (course CourseController) Select(c *gin.Context) {
var courses []bean.Course
// 查询 JAVA 课程的学生选修情况(排除学生姓名为 xumeng03 的)
model.DB.Preload("Students", func(db *gorm.DB) *gorm.DB {
return db.Order("id desc")
}).Where("name=?", "JAVA").Find(&courses)
c.JSON(http.StatusOK, courses)
}
7、事务
func (student StudentController) Transfer(c *gin.Context) {
id1, _ := strconv.Atoi(c.Param("id1"))
id2, _ := strconv.Atoi(c.Param("id2"))
coin, _ := strconv.Atoi(c.Param("coin"))
tx := model.DB.Begin()
defer func() {
tx.Rollback()
}()
var user1 = bean.Student{Id: id1}
tx.Find(&user1)
user1.Coin += coin
tx.Save(&user1)
var user2 = bean.Student{Id: id2}
tx.Find(&user2)
user2.Coin -= coin
tx.Save(&user2)
tx.Commit()
}
8、配置文件
文档地址:https://ini.unknwon.io/
8.1、安装依赖
go get -u gopkg.in/ini.v1
8.2、数据准备
author = xumeng03
last-time = 2023-11-15 23:41:13
[APP]
name = gorm-study
[mysql]
ip = 127.0.0.1
port = 3306
username = root
password = Chace2233.
db = study
8.3、读取数据
package model
import (
"fmt"
"gopkg.in/ini.v1"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"os"
)
var DB *gorm.DB
var err error
func init() {
cfg, err := ini.Load("./config/config.ini")
if err != nil {
fmt.Printf("Fail to read file: %v", err)
os.Exit(1)
}
// author="xumeng03"
fmt.Println(cfg.Section("").Key("author").String())
// [APP] name="gorm-study"
fmt.Println(cfg.Section("APP").Key("name").String())
// [mysql] ip=127.0.0.1 port=3306
username := cfg.Section("mysql").Key("username").String()
password := cfg.Section("mysql").Key("password").String()
ip := cfg.Section("mysql").Key("ip").String()
port := cfg.Section("mysql").Key("port").String()
db := cfg.Section("mysql").Key("db").String()
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", username, password, ip, port, db)
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
// 配置跳过事务
SkipDefaultTransaction: false,
})
if err != nil {
fmt.Println(err)
}
}
8.3、写入数据
package model
import (
"fmt"
"gopkg.in/ini.v1"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"os"
"time"
)
var DB *gorm.DB
var err error
func init() {
cfg, err := ini.Load("./config/config.ini")
if err != nil {
fmt.Printf("Fail to read file: %v", err)
os.Exit(1)
}
// 读取数据
fmt.Println(cfg.Section("").Key("author").String())
fmt.Println(cfg.Section("APP").Key("name").String())
username := cfg.Section("mysql").Key("username").String()
password := cfg.Section("mysql").Key("password").String()
ip := cfg.Section("mysql").Key("ip").String()
port := cfg.Section("mysql").Key("port").String()
db := cfg.Section("mysql").Key("db").String()
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", username, password, ip, port, db)
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
// 配置跳过事务
SkipDefaultTransaction: false,
})
if err != nil {
fmt.Println(err)
}
// 写入数据
cfg.Section("").Key("last-time").SetValue(time.Now().Format("2006-01-02 15:04:05"))
cfg.SaveTo("./config/config.ini")
}