- 博主简介:努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:数据结构、Go,Java等相关知识。
- 博主主页: @是瑶瑶子啦
- 所属专栏: GORM框架学习
- 近期目标:写好专栏的每一篇文章
文章目录
- 一、准备工作
- 二、增(Create)
- 1.1:添加一条记录
- 1.2:批量插入
- 三、查询
- 3.1:查询单条记录
- 3.2:查询多条记录
- 3.3:获取查询结果
- 四、改
- 五、删除
一、准备工作
在上一篇Gorm文章中,我们学习了如何使用gorm进行数据库的连接和一些高级配置、简单操作。👉【GORM框架】模型定义超详解,确定不来看看?
今天,我们要学习,如何使用gorm,进行单表的CRUD操作
在学习CRUD之前,这是一些准备工作:
有一个golang项目,其中连接
是只负责和数据库进行连接
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
func init() {
username := "root" //账号
password := "55667788" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名(这里用的就是localhost,是一个回送地址,值本地机
port := 3306 //数据库端口
Dbname := "testdb" //数据库名
timeout := "10s" //连接超时,10秒
// root:root@tcp(127.0.0.1:3306)/gorm?
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
db, err := gorm.Open(mysql.Open(dsn))
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
// 连接成功
fmt.Println(db)
//把其DB类型实例赋给定义好的全局变量
DB = db
}
再新建文件.go
文件,进行CRUD练习
按住
ctrl
,点击多个.go
文件,再右键go run
,即可一次性运行多个go文件,但是注意,只能有一个main函数
这是模型定义:
// 1)模型定义:(表结构)
type Student struct {
ID uint `gorm:"size:3"`
Name string `gorm:"size:8"`
Age int `gorm:"size:3"`
Gender byte
Email *string `gorm:"size:32"`
}
注意!!!
- 为什么要把Email定义成指针类型呢?是为了更好的存储
null
类型。 - 因为string在Go中是值类型,当string没有被赋值时,默认是空串
""
。它是长度为0,同样占存储空间的字符串。而不是明显的告诉我们:这是一个空!!这样会引起混淆 - 相比之下,用指针类型,如果没有给出email,那就直接是
空:null
,既不会引起混淆,也可以节省空间(因为不会开辟内存)
二、增(Create)
1.1:添加一条记录
记录对应到代码里,其实就是结构体实体,所以我们只需实例化结构体,再使用gorm函数,进行create,即可建立联系,在数据库中增加记录
func main() {
//2)建表
DB.AutoMigrate(&Student{})
//3)添加记录(实例化结构体)
email := "3051337060@qq.com"
s1 := Student{
Name: "瑶瑶子",
Age: 19,
Gender: 'F',
Email: &email,
}
//把该实体映射到表中的记录:
err := DB.Create(&s1).Error
fmt.Println(err)
}
注意!!!
Create
函数接收的是指针
1.2:批量插入
批量插入也是用到Create
方法,需要使用到Go中的切片
//批量插入记录
//1)首先定义一个切片,用于存储多条记录
var studentList []Student
//2)向切片输入
for i := 0; i < 100; i++ {
studentList = append(studentList, Student{
Name: fmt.Sprintf("瑶瑶子%d号", i+1),
Age: 19,
Gender: 'F',
Email: &email,
})
}
//3)直接将整个切片传入
DB.Create(&studentList)
三、查询
3.1:查询单条记录
我们先来看一种比较简单的,使用Take()
函数,查询一条记录:
- 使用
Take()
函数,查询单条记录:
Take()
函数将从数据库表中获取任何一条符合条件的记录。是根据数据库表中的主键或者默认排序规则来获取的。
//定义一个结构体实体,用于存储数据库查询的返回的记录
var student Student
//使用gorm库中的方法,从数据库获取一条记录,映射到student变量中
DB.Take(&student)
fmt.Println(student)
注意:若上面已经执行了添加记录的语句,在执行查询语句时,需要把上面的增加语句注释掉,否则又会重复添加
First()
和Last()
函数,返回查询结果集合的第一条、最后一条记录
DB.First(&student)
// SELECT * FROM `students` ORDER BY `students`.`id` LIMIT 1
DB.Last(&student)
// SELECT * FROM `students` ORDER BY `students`.`id` DESC LIMIT 1
如果没有指定排序顺序,默认是按主键顺序升序排序ordered by `students`.`id`.
- 根据给定主键参数进行查询
var stu Student
DB.Take(&stu, 3)
fmt.Println(stu)
// SELECT * FROM `students` WHERE `students`.`id` = 3 LIMIT 1
- 根据其他字段进行查询
var stu Student
DB.Take(&stu, "name = ?", "瑶瑶子")
fmt.Println(stu)
注意,这里使用
?
作为占位符,原理是将用户输入进行转义后,再拼接。防止sql
注入问题
3.2:查询多条记录
Find()
查询数据库中所有与条件匹配的记录(以切片形式返回),如果没有,则返回空切片
var students []Student
DB.Find(&students)
for _, student := range students {
fmt.Println(student)
}
- 根据主键进行查找
var students []Student
DB.Find(&students, []int{1, 3, 5, 6})
DB.Find(&students, 1, 3, 5, 6) //和上面等价
fmt.Println(students)
- 根据其他条件查询
var students []Student
DB.Find(&students, "name in ?", []string{"瑶瑶子3号", "瑶瑶子6号"})
3.3:获取查询结果
- 获取查询的记录数
var students []Student
DB.Find(&students)
//核心代码如下行
count := DB.Find(&students).RowsAffected
fmt.Println(count)
- 是否查询失败
var students []Student
err := DB.Find(&students).Error
switch err {
case gorm.ErrRecordNotFound:
fmt.Println("没有找到")
default:
fmt.Println("sql错误")
}
四、改
Save()
进行单个记录的全字段更新
//1)先找到要修改的记录
var student Student
DB.Take(&student, 11)
//2)对其字段进行修改
student.Name = "是瑶瑶子啦"
//3)使用sava,进行保存(数据库内相映射的记录更新)
DB.Save(&student)
// UPDATE `students` SET `name`='是瑶瑶子啦',`age`=19,`gender`email`='3051337060@qq.com' WHERE `id` = 11
注意:零值也会被更新(即将字段修改为零值,使用sava,其在数据库映射也会被修改)
Select()
更新指定字段
可以看到,上面
save()
语句翻译成sql是进行全字段更新,即使只修改了一个。
使用select,则进行指定字段更新
//1)先找到要修改的记录
var student Student
DB.Take(&student, 11)
//2)对其字段进行修改
student.Name = "是瑶瑶子啦"
//3)使用sava,进行保存(数据库内相映射的记录更新)
DB.Select("Name").Save(&student)
// UPDATE `students` SET `name`='是瑶瑶子啦' WHERE `id` = 11
- 批量更新
//1)让所有年龄为19的年龄全修改为20(使用了其他属性查询
var students []Student
DB.Find(&students, "age = ?", 19).Update("Age", 20)
//2)将ID为1,2,3的年龄改为21(使用主键查询
DB.Find(&students, 1, 2, 3).Update("Age", 21)
- 使用结构体更新多字段(不会更新零值)
var students []Student
DB.Find(&students, 1, 2, 3).Updates(Student{
Name: "yyz",
Age: 0, //结构体更新零值,不会进行修改
})
fmt.Println(students)
//结果:[{1 yyz 21 70 0xc00022c940} {2 yyz 21 70 0xc00022c960} {3 yyz 21 70 0xc00022c980}]
- 使用map更新多字段(会更新零值)
DB.Model(&Student{}).Where("age = ?", 21).Updates(map[string]any{
"age": 0,
"name": "yyz2024",
})
//UPDATE `students` SET `age`=0,`name`='yyz2024' WHERE age = 21
五、删除
delete()
根据主键进行删除
DB.Delete(&student, 2)
// DELETE FROM `students` WHERE `students`.`id` = 2
delete()
根据主键批量删除
DB.Delete(&student, 12, 13)
// DELETE FROM `students` WHERE `students`.`id` IN (12,13)
delete()
+其他条件,批量删除
DB.Delete(&Student{}, "name = ?", "是瑶瑶子啦")
//DELETE FROM `students` WHERE name = '是瑶瑶子啦'
delete()
+where(其他条件)
批量删除
//批量删除
DB.Where("name = ?", "瑶瑶子").Delete(&Student{})
// DELETE FROM `students` WHERE name = '瑶瑶子'
注意:
- 警告 删除记录时,请确保主键字段有值,GORM 会通过主键去删除记录,如果主键为空,GORM 会删除该 model 的所有记录。
- 如果一个 model 有
DeletedAt
字段,他将自动获得软删除
的功能! 当调用 Delete 方法时, 记录不会真正的从数据库中被删除, 只会将DeletedAt 字段的值会被设置为当前时间
欢迎在评论区交流和留下你的想法和建议
如果对你有用,还请:💭评论+👍🏻点赞+⭐收藏+➕关注
-
Java岛冒险记【从小白到大佬之路】
-
GORM框架学习
-
Mysql从入门到精通
-
Go语言核心编程
-
LeetCode每日一题–进击大厂
-
算法
-
C/C++
-
数据结构