一、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还支持MySQL
、SQLServer
等主流数据库。
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语句的order
、group
、limit
等子句抽象成了方法,可以在增删改查操作前进行设定。
GORM的删改查方法还支持内联条件,即将条件作为参数传入函数。
3.查
可以调用First
、Last
、Take
等方法获取符合条件的单个对象。这些方法返回一个对象
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{})
五、总结
-
- 使用时要导入gorm核心包以及对应的数据库的驱动包
-
- 创建时使用
db.Create
方法,传入一个对象或对象切片
- 创建时使用
-
- GORM中可以使用
Where
、Limit
、Order
等方法设定需要满足的条件
- GORM中可以使用
-
- 查找使用
db.First
等方法可以查找单条对象,使用db.Find
可以查找多条对象,可以指定条件
- 查找使用
-
- 使用
db.Update
来更新单列,db.Updates
更新多列
- 使用
-
- 若包含
gorm.deletedat
会进行软删除,否则是物理删除。
- 若包含