GORM v2的使用

前言

之前一直使用的是Gorm的v1,有些地方也觉得不方便,正好今天需要在原生sql语句后用count计数功能,则看了Gorm版本v2的更新,发现有很多新的玩法,就记录下自己工作中遇到的情况

Gorm官方文档

Gorm文档

安装Gorm v2

GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server

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

如果安装sqlite可能会报错

1
exec: "gcc": executable file not found in %PATH%

原因是sqlite 3是个cgo库,需要gcd编译c代码,需要安装mingw

解决方法

  • 下载mingw安装包

  • 解压后将bin路径加入环境变量

  • 终端中输入 gcc --version有相关信息则说明安装成功

添加后如果还是运行失败,就是环境变量更改未生效,重启电脑就可以了

安装Msyql驱动并使用

1
go get gorm.io/driver/mysql
1
2
3
4
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}

这里就比v1体验更好,v1中经常忘记引入驱动 import _ "github.com/jinzhu/gorm/dialects/mysql"

Mysql驱动程序提供了一些高级配置可以在初始化的时候使用

1
2
3
4
5
6
7
8
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
DefaultStringSize: 256, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}), &gorm.Config{})

操作

原生sql语句

通过db.Raw设置sql语句,通过Scan执行查询

1
db.Raw("SELECT id, name, age FROM users WHERE id = ?", 3).Scan(&result)

使用原生sql后的Scan不能跟Count

Exec 原生 SQL

1
db.Exec("UPDATE orders SET shipped_at=? WHERE id IN ?", time.Now(), []int64{1,2,3})

raw后接count

在GORM v1中使用原生sql语句Raw后不能接Find,只能Scan,并且Scan后不能使用计数Count

在v2中Scan后可以接Count,并且Raw后也可以接Find

1
DB.DB.Raw("select *from articles where user_id = ? ",u.ID).Find(&articles).Count(&count).Error
1
DB.DB.Raw("select *from articles where user_id = ? ",u.ID).Scan(&articles).Count(&count).Error

预加载

GORM v2 允许在 Preload 的其它 SQL 中直接加载关系

例如:user中有card数组,使用

1
db.Preload("Cards").Find(&users)

就可以将相关card信息从cards数据表中也添加到users结构体中

命名参数

GORM 支持 sql.Namedmap[string]interface{}{} 的命名参数

1
DB.DB.Model(model.Article{}).Where("user_id=@id", sql.Named("id", u.ID)).Find(&articles).Count(&count).Error
1
DB.DB.Raw("select *from articles where user_id = @id ", map[string]interface{}{"id":u.ID}).Scan(&articles).Error