这是青训营笔记的第一篇文章。
使用GORM连接MySQL数据库并实现CRUD
准备工作
安装GORM
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
创建一个用于测试的test库
命令行,MySQL workbench,datagrip任君选择
基本要素
数据库连接
首先根据数据库配置,获取对应的DSN,具体格式为 {用户名}:{密码}@tcp({服务器地址}:{端口号})/{数据库名称}?{配置信息,如字符集指定等}
import (
"gorm.io/driver/mysql"//此处务必使用
//gorm提供的MySQL驱动,使用官方驱动会出错
"gorm.io/gorm"
)
func main() {
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
更多进阶内容请移步官方文档gorm.io/zh_CN/docs/…
定义数据模型
模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成 此教程中,我们简化官方文档的实例代码,定义User作为数据模型
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
```
使用语句
```go
db.AutoMigrate(&User{})
// 可以通过Set设置附加参数,下面设置表的存储引擎为InnoDB
db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})
GORM将会根据User声明自动生成对应的表Users
进行数据库操作
基本范式:按照MySQL语句的执行顺序调用方法 GORM本质上是一个SQLY语句生成软件,通过迁移SQL逻辑,我们可以快速上手GORM
创建
创建单项记录
user := User{Name: "Xiaolin", Age: 18, Birthday: time.Now()}
result := db.Create(&user) // 通过数据的指针来创建
//使用result接收数据库返回,将记录打印到标准输出或者日志
user.ID // 返回插入数据的主键
result.Error // 返回 error
result.RowsAffected // 返回插入记录的条数
创建多项记录
users := []*User{
User{Name: "Xiaolin", Age: 18, Birthday: time.Now()},
User{Name: "Jackson", Age: 19, Birthday: time.Now()},
}
result := db.Create(users) // pass a slice to insert multiple row
result.Error // returns error
result.RowsAffected // returns inserted records count
用指定的字段创建记录
db.Select().Create()
db.Omit().Create()
查询
最简单的查询
假设我想要查询上述所创建表中的单个记录,GORM 提供了 First、Take、Last 方法,在没有找到记录时,它会返回 ErrRecordNotFound 错误。
// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;
result := db.First(&user)
result.RowsAffected // 返回找到的记录数
result.Error // returns error or nil
// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)
如果要避免ErrRecordNotFound 错误,可以使用Find,如:
db.Limit(1).Find(&user)
值得注意的是,对单个对象使用Find而不带limit,db.Find(&user)将会查询整个表并且只返回第一个对象,这是性能不高并且不确定的。
当目标对象有一个主键值时,将使用主键构建查询条件,例如:
var result User
db.Model(User{ID: 10}).First(&result)
// SELECT * FROM users WHERE id = 10;
使用Find方法,可以查询所有符合条件的对象
// Get all records
result := db.Find(&users)
// SELECT * FROM users;
result.RowsAffected // returns found records count, equals `len(users)`
result.Error // returns error
带条件查询
GROM支持多种条件输入方式:
- String条件
- Struct&Map条件
- SQL注入
String条件
一言以蔽之,就是以? 作为占位符,通过格式化字符串的输入方式来编写条件,例如:
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
Struct & Map 条件
Struct & Map 本身就是一种对应关系的抽象数据结构,这就更好理解了
// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 ORDER BY id LIMIT 1;
更新
保存所有字段
Save 会保存所有的字段,即使字段是零值。 Save 方法是一个组合逻辑函数。如果要保存的值不包含主键,他会执行Create,否则执行Update。
db.First(&user)
user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)
db.Save(&User{Name: "jinzhu", Age: 100})
// INSERT INTO `users` (`name`,`age`,`birthday`,`update_at`) VALUES ("jinzhu",100,"0000-00-00 00:00:00","0000-00-00 00:00:00")
更新单列
首先输入约束条件,然后执行Update操作
// Update with conditions
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;
更新多列
在单列语句的基础上,将Update中的语句替换为Struct & Map。 需要注意的是,使用struct更新,只会更新非0的数据。
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 = 111;
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
更新选定字段
使用Select或者Omit方法
// User's ID is `111`:
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
删除
删除一条记录时,删除对象需要指定主键,否则会触发 批量删除,例如:
// Email 的 ID 是 `10`
db.Delete(&email)
// DELETE from emails where id = 10;
// 带额外条件的删除
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
总结
在使用GORM框架时,只需要遵循SQL语句的逻辑,调用对应的方法,便可以轻易实现go程序到数据库的连接。