使用 GORM连接数据库,并实现增删改查操作 | 豆包MarsCode AI刷题

30 阅读5分钟

参考了官方文档其中文版

一、ORM简介

在Web开发过程中不可避免的要操作数据库,编程语言原生的数据库模块有一系列问题。如执行效率问题、设计难度问题、迁移问题和安全性问题。 ORM(Object Relational Mapping,即对象关系映射),使得我们可以基于面向对象的思想去编写类、对象、调用相应的方法等,ORM会将其转换/映射成原生SQL然后操作数据库。ORM将数据库中的表转为程序中的对象,通过建立对象和关系数据之间的映射模型,可以将一个表对应一个类;将一条记录对应一个对象。 GORM是Go语言的一个ORM库,我们可以利用GORM和Go语言实现对数据库的操作。

二、GORM特性

摘自官方文档,包括

  • 全功能
  • 支持事务
  • 开发者友好 ......

三、GORM操作

1.安装

通过以下命令安装,注意需要先初始化go module,如果没有需要执行go mod init。 这里我们主要是实现对sqlite进行操作。

go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite

2.导入

import (
   "gorm.io/gorm"
   "gorm.io/driver/sqlite"
)

其中gorm.io/gorm是GORM的核心库,gorm.io/driver/sqlite是数据库驱动,用于操作sqlite数据库。GORM还支持MySQLSQLServer等主流数据库。

3.连接数据库

我们通常使用gorm.Open方法建立数据库连接,与SQLite建立连接的代码如下(我们创建了一个名为test.db的数据库文件,并于它连接)。

db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
   panic("Connect failed")
}

4.模型定义

模型是标准的 struct,只需要按照Go语言标准定义一个struct即可。

5.gorm.Model

gorm.Model是一个GORM中提供的内置结构体,包含以下常用字段:

  • ID:主键
  • CreatedAt:创建时间
  • UpdatedAt:更新时间
  • DeletedAt:删除时间(软删除) 通常我们可以通过以下的方式将gorm.Model嵌入我们定义的结构体中,这样我们定义的结构体也拥有了gorm.Model的字段。
type User struct {
   gorm.Model
   UserName string
   Age uint
}

6.高级选项

(1)嵌入 可以通过gorm:"embedded"将一个结构体A嵌入另一个结构体B,这样B结构体同样具有了A结构体的字段。 如下

type Author struct {
    Name  string
    Email string
}
type Blog struct {
  ID      int
  Author  Author `gorm:"embedded"`
}

(2)读写控制 还可以通过对结构体字段添加标签,实现对结构体字段的读写权限的控制。 因为涉及的标签较多,请参考GORM官方文档的说明。

四、GORM实现CRUD(增删改查)

1.增

新增一条记录,通常我们使用db.Create方法并且传入一个结构体指针。

db.Create(&User{Name:"A", Age:18})

如果需要批量更新的话,我们会创建一个结构体的slice,并将slice传递给db.Create方法。如下

var users = []User{
   {Name: "B", Age: 20}, 
   {Name: "C", Age:30}, 
   {Name: "D", Age:24}
}
db.Create(&users)

GORM将自动填入主键,并生成SQL语句插入所有数据。 GORM还支持使用选定的字段创建对象。 使用db.Select方法时,我们传入参数作为需要被赋值(更新)的字段,使用db.Create方法时,GORM会创建一条记录,并且将db.Select中指定的字段的值。

user1 := User{Name: "E1", Age:  20}
db.Select("Name").Create(&user1)

使用db.Omit方法可以在创建记录时,不对某一字段进行赋值(即排除了某一字段)

user2 := User{Name:"E2", Age: 21}
db.Omit("Age").Create(&user2)

需要注意的是,GORM会默认处理一些字段,即使我们没有设定这些字段的值

  • 有PrimaryKey标签的字段,会自动创建,即便不在Select中
  • 有Default标签的字段,会直接赋值为设定的默认值
  • 模型中的CreatedAt,UpdatedAt等通用字段会被自动创建

2.条件

GORM中使用db.Where方法设定条件,这在查、改、删等操作时非常有效。 通常可以在db.Where中传入字符串,字典,切片等方法作为条件,具体可以参考官方文档。 GORM还将SQL语句的ordergrouplimit等子句抽象成了方法,可以在增删改查操作前进行设定。 GORM的删改查方法还支持内联条件,即将条件作为参数传入函数。

3.查

可以调用FirstLastTake等方法获取符合条件的单个对象。这些方法返回一个对象

var oneUser User
var lastUser User
db.First(&oneUser)
db.Last(&lastUser, User{age: 20})

可以调用Find方法返回一组对象,通常需要用一个对象切片接收

var users []User
db.Find(&users)
db.Where("age = ?", "20").Find(&users)

4.改

使用Update更新

db.Model(&User{}).Where("name = ?", "A").Update("age", 4)

5.删

GORM中利用db.Delete方法删除记录。

5.1 物理删除

通常情况下,GORM删除一个记录采用物理删除的方式,即彻底从文件系统中删除。

type NewUser struct {
   Name string
   Age uint
}
// 删除一条记录
db.Delete(&User{}, 4)
// DELETE from `users` where `users`.`id` = 4;
// 批量删除
db.Delete(&User{}, []int{1, 2, 3})
// 依照条件删除
db.Where("name = ?", "A").Delete(&User{})

需要注意的是,当Delete方法不添加主键时,默认为批量删除。如果没有指定主键且指定了删除的条件(Where方法),则GORM会删除所有匹配的选项。如果在没有任何条件的情况下执行批量删除,GORM 不会执行该操作,并返回 ErrMissingWhereClause错误

5.2 软删除

如果模型包含了一个 gorm.deletedat字段(gorm.Model已经包含了该字段),调用db.Delete将自动执行软删除。软删除指记录仍然存在于文件系统中,但我们无法通过正常的查询操作查询到该记录。GORM 会将 DeletedAt 置为当前时间,表示该对象已被删除。

type User struct {
	gorm.Model
	Name string
	Age  uint
}
db.Delete(&User{}, 5)
db.Where("name = ?", "A").Delete(&User{})

5.3 操作被软删除的记录

可以使用Unscoped找到被软删除的记录

users := make([]User, 10)
db.Unscoped().Where("name = ?", "A").Find(&users)

我们还可以使用Unscoped也可以实现对软删除数据的物理删除

db.Unscoped().Where("name = ?", "A").Delete(&User{})

五、总结

    1. 使用时要导入gorm核心包以及对应的数据库的驱动包
    1. 创建时使用db.Create方法,传入一个对象或对象切片
    1. GORM中可以使用WhereLimitOrder等方法设定需要满足的条件
    1. 查找使用db.First等方法可以查找单条对象,使用db.Find可以查找多条对象,可以指定条件
    1. 使用db.Update来更新单列,db.Updates更新多列
    1. 若包含gorm.deletedat会进行软删除,否则是物理删除。