GORM基础实践 | 青训营

76 阅读5分钟

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 方法会保存所有的字段,即使字段是对应类型的零值。