GORM(Go 的 ORM 库)数据库操作实践 | 青训营

84 阅读6分钟

GORM是go语言中的一款ORM库,它为Web项目连接数据库从而进行数据库操作提供强大的功能和简洁的API,包括数据库连接、CRUD操作、事务管理等。接下来以简易抖音项目为例展示GORM的一些基础使用方法。

数据库连接

gorm库怎么安装比较简单,大家可以自行网上搜索安装即可。对于在web项目中使用gorm连接数据库,主要使用了gorm.Open()的这个接口:

1692585969986.png

从上图看到,我们以连接mysql数据库为例,数据库的连接信息先被保存到一个变量dsn中。从左到右的红色框中,第一个定义了连接数据库的用户名为root,其后跟着的是用户登陆数据库的密码。第二个红色框说明了我们通过IP地址加端口来连接到mysql的服务器。第三个红色框告诉了mysql我们想连接tiktok这个数据库。随后把这些信息作为参数传给gorm.Open()来连接数据库

CRUD操作

对于gorm的CRUD操作,一般做法是对于某个表的CRUD都会创一个相对应的.go文件来执行。比如说:

1692586502195.png

上图展示的是user这个表对应的user.go文件来存放CRUD操作。通过定义User结构体的TableName()函数来告诉mysql这里的CRUD是针对users表进行的。当然也有其他办法比如说在CRUD的时候通过.Model()来指向操作的对象是哪个表。

定义完TableName()后,NewUserDaoInstance()会被定义来创建一个UserDao实例进行CRUD操作,因为接下来CRUD函数的定义都是被定义为Dao结构体的函数,所以需要实例化一个Dao对象来执行这些操作。

Create

1692586943382.png

图中所示的create操作也是在上面定义好的user.go文件下的创建用户函数。从上由下看,第一个红框表示CreateUser()函数被定义为UserDao结构体的函数,所以执行的时候需要UserDao实例来进行调用。在函数内部,第二个红框为我们将要创建的user对象,定义好相对的数据后,执行create操作的是第三个红框里的db.Create()。db即为我们在连接数据库时gorm.Open()得到的mysql数据库对象。通过调用db.Create()接口,把想要创建的用户对象作为参数传入即可完成create操作。当然创建操作是有可能出错的,所以相对应的错误处理是不能省略的。

Retrieve

gorm提供了许多方法来支持SQL查询操作,以下列出其中的一些:

  • db.First();可以查询表中匹配的第一条记录,如果无匹配数据会返回gorm.RecordNotFound的错误,需要进行处理。
  • db.Find();可以查询表中匹配的所有记录,所以返回的是一个列表,如果无匹配数据则会返回一个空列表,无错误返回
  • db.Last();可以查询最后一条记录

查询中可以使用Where来限制查询的条件,比如说想要查询特定用户名的某一条用户数据:

result := db.Where("name == ?", username).Find(&users)

也可以使用.Order()来自定义排序的规则,用法与.Where()类似: result := db.Opem("id desc").Find(&users)

使用Count来统计记录的条数: result = db.Model(&User{}).Count(&count) 这里使用.Model()来指明执行操作的表,并定义了一个int64类型的变量count来作为Count()的参数传入获取记录的条数。

接着上面的创建操作,下面是执行根据username来查询user的查询过程:

1692588836750.png

这个查询函数也是定义为UserDao结构体的函数。主要操作为第二个红框的Find()接口。首先第一个红框定义了一个User结构体的列表变量users,因为我要用db.Find()来进行我的查询,而它返回的是一个列表对象。在查询操作中.Where()也应用其中来限制查询的条件为username。所以最终得到到返回结果为符合username的user对象。

我之所以选择使用db.Find()而不使用db.First()是因为Find()查询操作不会有RecordNotFound这个错误出现,所以我不需要考虑处理这个错误,我只需要判断Find()返回的查询结果列表是否为空来判断存不存在记录即可。

Update

gorm的更新操作也有两种方法,第一种是使用db.Save(),第二种是使用db.Update()。

db.Save()

使用这种方法前提是基于先查询,先查询出你想要更新的数据,然后对查询到的数据进行修改后,再把修改后的数据作为参数传入db.Save()来保存更新。

在这种更新操作下,你要确保更新的数据是存在表中的,不然就会变成创建操作了。这种更新操作个人觉得表复杂,所以更倾向于第二种方法。

db.Update()

1692589493967.png

可以看到,我这里执行的是usertoken的更新操作就是使用了db.Updates()接口,db.Updates()与db.Update()的区别就是在于你是更新一条数据还是更新多条。

Update()的方法有一个不同之处在于其只会更新非零值的字段,如果你传入update要更新的字段值为0,它则不会进行更新操作。要解决这个办法呢,就可以将结构体换成map[string]interface{}类型的map对象,像上图的第一个红框,每隔一段时间user的token字段就要进行更新,所以将要更新的LoginUserData结构体中的token字段定义为map类型对象再进行传入。在上图中,第二个红框为更新操作的语句,在Update()中也可以使用.Where来限制更新的条件。编写起来也是极其简单。

Delete

gorm的删除操作也是比较完善的,提供了软删除和完全删除的办法。gorm默认使用的是软删除策略也就是逻辑删除。

1692590508975.png

上图中实现的是简易抖音的评论删除操作。可以看到该删除是基于id删除的,所以.Where会用在删除操作上来限制删除条件。整个操作起来也是非常的简单,5行代码搞定。

上面说了这样的删除操作其实是逻辑删除,对于比较重要的数据逻辑删除可以更好的保存这些数据。逻辑删除后的数据在查询以及更新的时候是不会被查询到的。如果要进行完全删除也就是物理删除,可以调用gorm的.Unscoped()方法来实现: result := db.Unscoped().Where("id=?", id).Delete(&comment)

总结

整体来说gorm的CRUD操作是十分方便且简单的,在连接好数据库之后就可以开始进行各种sql操作了。在实践之后也发现比较好上手,更多的功能以及用法还有待学习,不过目前对于CRUD也比较熟悉算是开了个好头!