- 博主简介:努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:数据结构、Go,Java等相关知识。
- 博主主页: @是瑶瑶子啦
- 所属专栏: GORM框架学习
- 近期目标:写好专栏的每一篇文章
在上一篇Gorm文章中,我们学习了如何使用gorm进行数据库的连接和一些高级配置、简单操作。【GORM框架】模型定义超详解,确定不来看看?
今天,我们要学习,如何使用gorm,进行单表的CRUD操作
在学习CRUD之前,这是一些准备工作:
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"`
}
注意!!!
null
类型。""
。它是长度为0,同样占存储空间的字符串。而不是明显的告诉我们:这是一个空!!这样会引起混淆空:null
,既不会引起混淆,也可以节省空间(因为不会开辟内存)记录对应到代码里,其实就是结构体实体,所以我们只需实例化结构体,再使用gorm函数,进行create,即可建立联系,在数据库中增加记录
func main() {
//2)建表
DB.AutoMigrate(&Student{})
//3)添加记录(实例化结构体)
email := "[email protected]"
s1 := Student{
Name: "瑶瑶子",
Age: 19,
Gender: 'F',
Email: &email,
}
//把该实体映射到表中的记录:
err := DB.Create(&s1).Error
fmt.Println(err)
}
注意!!!
Create
函数接收的是指针批量插入也是用到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)
我们先来看一种比较简单的,使用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
注入问题
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号"})
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`='[email protected]' 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}]
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 = '瑶瑶子'
注意:
DeletedAt
字段,他将自动获得软删除
的功能! 当调用 Delete 方法时, 记录不会真正的从数据库中被删除, 只会将DeletedAt 字段的值会被设置为当前时间欢迎在评论区交流和留下你的想法和建议
如果对你有用,还请:评论+点赞+⭐收藏+➕关注
Java岛冒险记【从小白到大佬之路】
GORM框架学习
Mysql从入门到精通
Go语言核心编程
LeetCode每日一题–进击大厂
算法
C/C++
数据结构