title: Gorm框架实践|青训营
categories: 青训营
实践选题: 使用 GORM(Go 的 ORM 库)连接数据库,并实现增删改查操作,把实现过程整理成文章;
1.准备工作
1.1 Gorm框架安装
使用Go自带的get进行安装,首先打开命令行(CMD或Shell),将路径切换至项目路径(go.mod所在路径),依次执行以下命令:
go get -u gorm.io/gormgo get -u gorm.io/driver/mysql
即可安装Gorm框架和Gorm的Mysql驱动,本文使用Mysql作为数据库,若使用其他数据库,请下载相应数据库驱动
1.2 DSN
Gorm框架的驱动使用DSN来连接数据库,因此需要配置DSN,DSN连接格式如下:
- user:password@tcp(127.0.0.1:3306)/database_name?charset=utf8mb4&parseTime=True&loc=Local
分别是:用户名,密码,服务器地址(127.0.0.1),端口(3306),数据库名称等
首次配置方法(Windows):
- 打开控制面板->管理工具->ODBC数据源->系统DSN
- 添加MySQL ODBC 8.0 Driver
- 设置数据源名称(随便命个名),TCP/IP 服务器地址(建议127.0.0.1:3306)
- 输入用户名和密码,MySQL存在的用户,要有对应的表权限,若输入正确则可以选择下一列的数据库名称
对应的DSN为: root:123456@tcp(127.0.0.1:3306)/bloginfos?charset=utf8mb4&parseTime=True&loc=Local
2.连接
首先根据表结构创建对应的结构体来映射数据库表, 如下所示
则创建User结构体来映射user表,结构体名可以与表名不一致,但TableName方法返回值必须与表名一致,因为Gorm通过TableName获取表名来生成SQL语句
添加gorm.Model则会自动生成create_at,updated_at和deleted_at字段,这些字段也会在表中被创建
!!!注意:结构体中的属性名必须有且仅有首字母大写,否则无法被映射
// 创建结构体用于映射数据库表,字段名和类型与数据库表字段一致
type User struct {
gorm.Model
ID int
Username string
Password string
Isonline string
}
// 用于返回获取表名
func (p *User) TableName() string {
return "User"
}
使用以下语句进行数据库连接并自动初始化
dsn := "root:123456@tcp(127.0.0.1:3306)/bloginfos?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
err = db.AutoMigrate(&User{})
if err != nil {
return
}
3.查询
3.1 查询方式
Gorm提供三种方式来查询一条单一数据,分别是:
First查询第一条数据(主键递增的第一条数据)Take查询一条数据,无顺序Last查询最后一条数据(即主键递减的第一条数据)
Gorm通过Find来查询所有符合条件的元组
注意参数要传递引用,因为Gorm通过修改参数来返回结果,若不传递引用则无法得到结果
对于没有设置主键的表,则按第一个字段排序
这三种方法可以设置查询条件,如下所示,对于Find方法,查询到的所有结果会以数组的方式存储在uesr中
var user User
var users []User
db.First(&user)
db.Take(&user)
db.Last(&user)
db.Find(&users)
也可以不指定对象类别,适用表名来进行查询
result := map[string]interface{}{}
DB.Table("user").Take(&result)
将查询到的users表中的数据结果存储到result中
3.2 条件查询
Gorm有多种方法设置查询条件,此处以First为例,条件设置方式适用于其他查询方法
查询条件都以字符串形式出现,为查询字段+值的形式设置,其中查询字段为: 字段名+约束方法+?的形式组成,约束方法可以设置为SQL中的方法如=,>,<,between,in等
- 主键查询:
db.First(&user, 1)查询主键值为1的元组 - 单一条件查询:
db.First(&user, "username = ?", "admin")查询用户名为admin的元组 - 多条件查询:
db.First(&user, []string{"username = ?", "admin", "password = ?", "123456"})
除了上述查询条件的设置方法,还有以下几种:
db.Where("name = ?", "jinzhu").First(&user)db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
也可以在一条字符串中设置多个查询条件,根据条件的数量依次读取后续参数作为查询值
db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20)
4.插入
可以直接通过Create创建,未初始化的值将被作为空值传递
user = User{Username: "Jinzhu", Password: "123456", Isonline: "false"}
db.Create(&user)
批量插入
var users = []User{{Username: "jinzhu1"}, {Username: "jinzhu2"}, {Username: "jinzhu3"}}
DB.Create(&users)
5.更新
更新使用Update函数,可以与Where搭配使用,同时若传递参数为示例,则会自动将该示例的主键作为一个条件
//这里仅指定表名
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;
db.Model(&user).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=user.id;
更新多个字段
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = user.id;
使用select仅更新指定字段,即使参数中有多个字段数据
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello' WHERE id=user.id;
6.删除
Gorm中提供了物理删除和软删除两种删除方法,物理删除将直接从数据库中删除该数据,而软删除会设置deleted_at字段而不会在数据库中删除,软删除后该条数据无法通过Gorm一般查询被查询到
6.1物理删除
若不指定条件,则按实例的主键作为条件删除对应数据,或与Where搭配使用
db.Delete(&user)
// DELETE from emails where id = user.id;
db.Where("name = ?", "jinzhu").Delete(&user)
// DELETE from emails where id = user.id AND name = "jinzhu";
不传递实例,按主键删除
db.Delete(&User{}, 1)
// DELETE FROM users WHERE id = 1;
db.Delete(&User{}, "1")
// DELETE FROM users WHERE id = 1;
db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);
批量删除,不传递实例
db.Where("username LIKE ?", "%jinzhu%").Delete(User{})
// DELETE from emails where email LIKE "%jinzhu%";
db.Delete(User{}, "username LIKE ?", "%jinzhu%")
// DELETE from emails where email LIKE "%jinzhu%";
6.2 软删除
若表中有gorm.DeletedAt字段,则该表可以使用软删除(该字段包含在gorm.Model中),软删除会被自动调用
软删除的原理是执行Update来为DeletedAt字段赋值为执行删除命令的时间
db.Delete(&user)// UPDATE users SET deleted_at=删除时间 WHERE id = user.id;
如果不想使用软删除,可以使用Uncoped执行下述命令
db.Unscoped().Delete(&order) // DELETE FROM orders WHERE id=10;
7.官方文档
更多详细内容可以参考Gorm官方文档