GORM
gorm是go语言中一个重要的orm库,用来连接和操作数据库
项目结构
│─ docker-compose.yaml
│─ go.mod
│─ main.go
└─config
└─sql
└─ init.sql
安装
在项目根目录下运行
go get -u gorm.io/gorm
数据库
要连接数据库,我们首先得有一个数据库
可以将数据库运行在本地,也可以运行在云端服务器上面
同时还可以使用docker来构建数据库方便管理
在这里我们就用docker来构建一个mysql数据库,数据库端口就是默认的3306
version: '3'
services:
db:
container_name: mysql
image: mysql
restart: always
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_DATABASE=demo
- TZ=Asia/Shanghai
- MYSQL_USER=demo
- MYSQL_PASSWORD=123456789
# 通过config/sql下面的sql脚本初始化数据库
volumes:
- ./config/sql:/docker-entrypoint-initdb.d/
ports:
- 3306:3306
这样我们的数据库就搭起来了,用户是demo,密码是123456789,同时我们通过config/sql文件夹下面的sql文件进行数据库的初始化
create table demo.users
{
id int auto_increment,
name varchar(32) not null,
password varchar(255) not null,
created_at datetime,
updated_at datetime,
deleted_at datetime,
primary key(id)
}
数据库连接
gorm中连接数据库是使用dsn字符串来连接
基本格式如下
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
user就是用户名,pass就是密码, dbname就是数据库的名字, charset就是字符集,parseTime是是否解析时间字符串,loc是地点
值得提一嘴的是mysql的utf8有两种一个是utf8mb3,一个是utf8mb4,其中mb3是阉割版,mb4才是完整的utf8
main.go
package main
import (
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "demo:123456789@tcp(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
return
}
sqlDb, err := db.DB()
if err != nil {
log.Fatal(err)
return
}
if err = sqlDb.Ping(); err != nil {
log.Fatal(err)
return
}
}
到这里我们的数据库已经连接上了
声明模型
我们目前的模型只有一个User,所以我们需要声明这个结构体为数据库模型
type User struct {
ID uint `gorm:"primaryKey"`
Name string
Password string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt
}
GORM 倾向于约定优于配置 默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间。
而DeletedAt是为了实现软删除而准备的。
增
增加一条记录我们需要先创建一个结构体的示例,将ID CreatedAt UpdatedAt DeletedAt留空
然后传入DB的创建函数, gorm会在数据库中创建一条记录,同时将ID CreatedAt UpdatedAt DeletedAt自动填充回示例中
user := User{
Name: "Mark",
Password: "MarkMark",
}
db.Create(&user)
fmt.Println(user)
fmt.Println(user.ID)
fmt.Println(user.Name)
fmt.Println(user.Password)
fmt.Println(user.CreatedAt)
fmt.Println(user.UpdatedAt)
fmt.Println(user.DeletedAt)
结果如下
{1 Mark MarkMark 2023-08-13 15:41:26.822 +0800 CST 2023-08-13 15:41:26.822 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}}
1
Mark
MarkMark
2023-08-13 15:41:26.822 +0800 CST
2023-08-13 15:41:26.822 +0800 CST
{0001-01-01 00:00:00 +0000 UTC false}
可以看到原本没有填写的字段ID现在被写入1
查
user = User{ID: 1}
db.First(&user)
fmt.Println(user)
fmt.Println(user.ID)
fmt.Println(user.Name)
fmt.Println(user.Password)
fmt.Println(user.CreatedAt)
fmt.Println(user.UpdatedAt)
fmt.Println(user.DeletedAt)
我们重新给user赋一个User结构体的实例,这个示例里面只有一个ID字段,gorm会自动检测ID,然后根据ID进行查询,并且将内容赋值到user的每一个字段里
结果如下
{1 Mark MarkMark 2023-08-13 15:46:46 +0800 CST 2023-08-13 15:46:46 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}}
1
Mark
MarkMark
2023-08-13 15:46:46 +0800 CST
2023-08-13 15:46:46 +0800 CST
{0001-01-01 00:00:00 +0000 UTC false}
改
time.Sleep(time.Second * 5)
user = User{ID: 1}
db.First(&user)
user.Password = "MarkkraM"
db.Save(&user)
省略了打印代码 gorm中的Save会保存实例中的所有值,哪怕是默认值 所以比较好的做法是先查,将查询结果保存的实例中,然后修改实例, 然后通过Save修改值,同时gorm会同时更新UpdatedAt的值
结果如下
{1 Mark MarkkraM 2023-08-13 16:32:23 +0800 CST 2023-08-13 16:32:27.877 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}}
1
Mark
MarkkraM
2023-08-13 16:32:23 +0800 CST
2023-08-13 16:32:27.877 +0800 CST
{0001-01-01 00:00:00 +0000 UTC false}
删
user = User{ID: 1}
db.Delete(&user)
gorm根据传入的实例的ID删除数据,由于我们设定了DeletedAt这个字段,所以删除后DeletedAt也有了数值。
结果如下
{1 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {2023-08-13 16:48:49.933 +0800 CST true}}
1
0001-01-01 00:00:00 +0000 UTC
0001-01-01 00:00:00 +0000 UTC
{2023-08-13 16:48:49.933 +0800 CST true}