GORM基础实践
什么是GORM
了解GORM之前,我们需要先知道什么是ORM,ORM是对象关系映射(Object Relational Mapping)的简称,说实话,很少看到一个词翻译为完整的英文后还是让人不好理解,简单来说,ORM在关系型数据库和对象之间做一个映射,方便开发者轻松加愉快的使用类似操作对象的方式而不是复杂的SQL语句来和数据库打交道。
那GORM呢,它是一个Go语言的ORM库,GORM是Go语言中最受欢迎的ORM库之一,它提供了强大的功能和简洁的API,让数据库操作变得更加简单和易维护。本文将介绍 GORM 的常见用法,包括数据库连接、模型定义、CRUD等方面。
连接数据库
GORM目前支持MySQL、SQLServer、PostgreSQL、SQLite。 GORM通过驱动来连接数据库,如果需要连接其他类型的数据库,可以复用/自行开发驱动。本文使用GORM + mysql展示GORM的基础用法。
首先下载GORM和MYSQL驱动
go get gorm.io/driver/mysql
go get gorm.io/gorm
然后连接数据库
username := "root" //账号
password := "root" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "gorm" //数据库名
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)
上面这段代码首先定义了连接数据库需要的一些一系列参数,包括账号(username)、密码(password)、数据库地址(host)、数据库端口(port)、数据库名(Dbname)和连接超时时间(timeout)。
然后,使用 fmt.Sprintf 函数将这些参数格式化成一个连接字符串(dsn),该字符串用于在 gorm.Open 函数中建立与 MySQL 数据库的连接。ps:dsn是数据源名称(Data Source Name)
接下来,调用 gorm.Open 函数,传入连接字符串,以打开与 MySQL 数据库的连接。如果连接失败,将抛出一个 panic 异常,打印出错误信息。
如果连接成功,将打印出连接成功的 db 实例。这个 db 实例是 gorm.DB 类型,可以用于后续的数据库读写操作。
模型定义
什么是模型,简单理解为对象,这个对象和数据库中的一行数据是一一对应的关系,一个模型,或者说一个对象,可以存储数据库中的一行
在Go语言中,模型是标准的struct
type User struct {
Name string `gorm:"column:name"`
Email *string `gorm:"column:email"`
Age uint8 `gorm:"column:age"`
Birthday *time.Time `gorm:"column:birthday"`
}
func (u *User) TableName() string {
return "user"
}
在上述的结构体中,通过gorm字段标签column来控制映射数据库中的字段名称。
提一嘴,GORM默认使用字段名的snake_case作为列名
最后一个func TableName()可以自定义表名,再提一嘴,GORM默认使用结构体名中的snake_case作为表名,不过在开发的时候我还是习惯加上列名标签和表名函数,默认的总是不那么直观。
接下来可以做一个快乐的CRUD仔了。
CRUD
创建记录
//构造user模型
now := time.Now()
email := "233333333@juejin.com"
user := User{Name: "user1", Email: &email, Age: 23, Birthday: &now}
//插入数据库
result := db.Create(&user) // 通过数据的指针来创建
要创建一条记录,我们需要先实例化User对象,然后将它的指针传递给db.Create方法
这个方法执行完后,返回一个db对象result。
从result中我们可以取到很多东西,比如说此次操作影响的行数result.RowsAffected;比如说此次操作是否出错result.Error。
查询单条记录
根据主键查询
var user User
db.Take(&user, 2)
根据主键查询记录,Take函数的第二个参数是主键
根据其他条件查询
var user User
db.Take(&user, "name = ?", "user1")
db.Where("name != ?", "user1").Find(&users)
上面这段代码相当于SQL语句
SELECT * FROM user WHERE name = 'user1' LIMIT 1
并且这个操作可以有效防止sql注入
查询多条记录
var users []User
// SELECT * FROM `user` WHERE name != 'unknown'
result = db.Where("name != ?", "unknown").Find(&users)
这里不再查询单条数据,所以改用 Find 方法来查询所有符合条件的记录。
删除记录
可以使用Delete方法删除记录
var user User
// UPDATE `user` SET `deleted_at`='2023-05-22 22:46:45.086' WHERE name = 'JiangHu' AND `user`.`deleted_at` IS NULL
result := db.Where("name = ?", "user1").Delete(&user)
我们可以看到,删除操作使用的是UPDATE,并且多了一个我们没定义的deleted_at字段,这个字段是怎么来的,下面进行解释。
对于删除操作,GORM 默认使用逻辑删除策略,不会对记录进行物理删除。这块有点复杂,GORM可以在定义模型时添加一个gorm.Model,这样,就可以使用这个方法来进行逻辑删除了,数据并不会真的从数据库删除,只是设置了一个deleted_at
更新记录
可以使用Update方法来更新字段的值
var user User
result := db.First(&user)
user.Name = "John"
user.Age = 20
// UPDATE `user` SET `name`='John',`email`='aaa@aaa.com',`age`=20,`birthday`='2023-05-22 22:14:47.813',
result = db.Model(&user).Update("name", "Jianghushinian")
是的,如果看对应的SQL语句,我们就知道Save 方法会保存所有的字段,即使字段是对应类型的零值。