0%

是时候升级GORM新版本了

多个golang项目中使用的 gorm 版本一直是 github.com/jinzhu/gorm v1.9.15 ,最近在处理数据库操作时又去gorm的官网上看了看官方文档,却发现按照官网文档中的介绍应用后却没有生效。

排查一番后才发现,gorm的版本更新了,现在官网上展示的默认文档是 v2.x 的使用文档,而 v2.x 和之前的 v1.x 相比是 完全的从零开始,某些方法在用法上已经更改了。

这里,列举两个比较明显的改变。

添加索引

通过gorm为指定的字段添加索引,在字段声明中设置索引和唯一索引:

1
2
3
4
type User struct {
AId int64 `json:"aid" gorm:"column:aid;not null;default:0;uniqueIndex:aid;comment:'视频id'"`
Name string `json:"name" gorm:"column:name;type:varchar(64);not null;default:'';index:name;comment:'视频名称'"`
}

结果在执行时只看到了一条创建索引的命令输出:

1
2
[2021-04-28 10:25:58]  [52.98ms]  CREATE INDEX name ON `archive_video`(name)   
[0 rows affected or returned ]

按照gorm官方文档中的介绍,uniqueIndex 标签的作用与 index 类似,它等效于 index:,unique

1
2
3
4
5
type User struct {
Name1 string `gorm:"uniqueIndex"`
Name2 string `gorm:"uniqueIndex:idx_name,sort:desc"`
Name3 string `gorm:"index:idx_name,unique"`
}

但在测试后发现,唯一索引 gorm:"uniqueIndex" 似乎不生效。

这就是其中的一个版本变化:

在 gorm v1 中,唯一索引使用 unique_index 下划线形式,而在 gorm v2 中,改成了使用 camelCase 风格的写法。

我使用的是 v1.9.15 版本,所以需要改成 unique_index 才行。

正确的 v1 风格的写法:

1
2
3
4
5
type User struct {
Name1 string `gorm:"unique_index"`
Name2 string `gorm:"unique_index:idx_name,sort:desc"`
Name3 string `gorm:"index:idx_name,unique"`
}

正确的 v2 风格的写法:

1
2
3
4
5
type User struct {
Name string `gorm:"index"`
Name2 string `gorm:"index:idx_name,unique"`
Name3 string `gorm:"uniqueIndex"`
}

批量插入

gorm v1 中不支持批量插入,v2 中才支持。

v2.x 中直接通过 db.model().create() 即可插入批量数据。一种示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 使用事务,批量插入
err = db.Transaction(func(tx *gorm.DB) error {

// create支持批量插入
var users = make([]model.User, 0)
for _, p := range info {
users = append(users, model.User{
CId: p.CId,
Name: p.Name,
Title: p.Title,
})
}

// 返回 nil 提交事务
return tx.Model(&model.User{}).Create(&users).Error
})

而在 v1.x 中,要想实现批量插入,可以通过执行 原生SQL(db.Exec) 的方法来完成。

mysql实现批量插入的sql语句为:

1
INSERT INTO `users` VALUES (?,?,?),(?,?,?),(?,?,?);

所以,只需要将要插入的数据进行一下sql拼接即可。

一种示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// BatchSave 批量插入数据
func BatchSave(db *gorm.DB, emps []*Employee) error {
var buffer bytes.Buffer
sql := "insert into `employees` (`name`,`age`,`addr`) values "
if _, err := buffer.WriteString(sql); err != nil {
return err
}
for i, e := range emps {
if i == len(emps)-1 {
// 最后一项
buffer.WriteString(fmt.Sprintf("('%s',%d,'%s');", e.Name, e.Age, e.Addr))
} else {
buffer.WriteString(fmt.Sprintf("('%s',%d,'%s'),", e.Name, e.Age, e.Addr))
}
}
return db.Exec(buffer.String()).Error
}

吐槽一下

在 gorm v2.x 的升级文档中看到下面的说明:

注意 GORM v2.0.0 发布的 git tag 是 v1.20.0

我当前使用的 v1.x 的版本是 v1.9.15 。不过看到官方的代码仓库中却找不到这个tag,能看到的只有如下的 v1.9.19

20210502170029

而我想要下载这个最高的版本 v1.9.19 ,却发现 go get github.com/jinzhu/gorm@v1.9.19 是找不到的。

一般来说按照惯例,大版本的变化应该定义为 v2.x.x 的tag才比较合适。

不得不说,gorm这个版本定义的还真让人迷糊啊。

另外一个槽点就是文档,我这代码要不报错,光看文档我还真不清楚文档和使用的版本是不一致的。


相关文档


如有疑问或需要技术讨论,请留言或发邮件到 service@itfanr.cc