gorm批量插入解决方案

简介: gorm批量插入解决方案

我有一个朋友, 最近用gorm发现官方不支持批量插入, 看官方issue 2014年就有人提过这个问题了, 不过现在还不支持


但是问题不大, 官方留出来一个执行原生SQL(db.Exec)的方法来解决这个问题, 而且官方现在在开发v2版本, 在v2版本中就会支持这个功能了


image.png


但是生活还得继续, bug还是得继续写, 本来想在网上找一个公用方法来维持一下生活, 结果竟然没找见!


20200415202812852.png


都是指定单个结构体去插入的


20200415203137638.png


这当然不行了, 写代码的意义不就是为了减轻重复的工作嘛, 既然这样, 就只能自己动手丰衣足食了

20200415203343988.png

下面为生成语句的方法

// GetBranchInsertSql 获取批量添加数据sql语句
func GetBranchInsertSql(objs []interface{}, tableName string) string {
  if len(objs) == 0 {
    return ""
  }
  fieldName := ""
  var valueTypeList []string
  fieldNum := reflect.TypeOf(objs[0]).NumField()
  fieldT := reflect.TypeOf(objs[0])
  for a := 0; a < fieldNum; a++ {
    name := GetColumnName(fieldT.Field(a).Tag.Get("gorm"))
    // 添加字段名
    if a == fieldNum-1 {
      fieldName += fmt.Sprintf("`%s`", name)
    } else {
      fieldName += fmt.Sprintf("`%s`,", name)
    }
    // 获取字段类型
    if fieldT.Field(a).Type.Name() == "string" {
      valueTypeList = append(valueTypeList, "string")
    } else if strings.Index(fieldT.Field(a).Type.Name(), "uint") != -1 {
      valueTypeList = append(valueTypeList, "uint")
    } else if strings.Index(fieldT.Field(a).Type.Name(), "int") != -1 {
      valueTypeList = append(valueTypeList, "int")
    }
  }
  var valueList []string
  for _, obj := range objs {
    objV := reflect.ValueOf(obj)
    v := "("
    for index, i := range valueTypeList {
      if index == fieldNum-1 {
        v += GetFormatField(objV, index, i, "")
      } else {
        v += GetFormatField(objV, index, i, ",")
      }
    }
    v += ")"
    valueList = append(valueList, v)
  }
  insertSql := fmt.Sprintf("insert into `%s` (%s) values %s", tableName, fieldName, strings.Join(valueList, ",")+";")
  return insertSql
}
// GetFormatField 获取字段类型值转为字符串
func GetFormatField(objV reflect.Value, index int, t string, sep string) string {
  v := ""
  if t == "string" {
    v += fmt.Sprintf("'%s'%s", objV.Field(index).String(), sep)
  } else if t == "uint" {
    v += fmt.Sprintf("%d%s", objV.Field(index).Uint(), sep)
  } else if t == "int" {
    v += fmt.Sprintf("%d%s", objV.Field(index).Int(), sep)
  }
  return v
}
// GetColumnName 获取字段名
func GetColumnName(jsonName string) string {
  for _, name := range strings.Split(jsonName, ";") {
    if strings.Index(name, "column") == -1 {
      continue
    }
    return strings.Replace(name, "column:", "", 1)
  }
  return ""
}
// BatchCreateModelsByPage 分页批量插入
func BatchCreateModelsByPage(tx *gorm.DB, dataList []interface{}, tableName string) (err error) {
  if len(dataList) == 0 {
    return
  }
  // 如果超过一百条, 则分批插入
  size := 100
  page := len(dataList) / size
  if len(dataList)%size != 0 {
    page += 1
  }
  for a := 1; a <= page; a++ {
    var bills = make([]interface{}, 0)
    if a == page {
      bills = dataList[(a-1)*size:]
    } else {
      bills = dataList[(a-1)*size : a*size]
    }
    sql := GetBranchInsertSql(bills, tableName)
    if err = tx.Exec(sql).Error; err != nil {
      fmt.Println(fmt.Sprintf("batch create data error: %v, sql: %s, tableName: %s", err, sql, tableName))
      return
    }
  }
  return
}

最后会返回批量插入的sql语句, 这样一来就舒服多了

因为我的朋友 现在类型主要用到了string, int和uint, 如果有其他类型需要加的话在 获取字段类型和GetFormatFeild里面加就行了

如果各位大佬有更好的解决方案希望可以拿出来分享学习一下

20200415202716469.png

目录
相关文章
|
消息中间件 Kafka
mac 搭建kafka系列教程
mac 搭建kafka系列教程
452 0
mac 搭建kafka系列教程
|
网络安全 开发工具 数据安全/隐私保护
|
9月前
|
C语言 图形学 Windows
Windows下安装和配置GTK4(基于CLion)
本文介绍了作者选择GTK作为C语言图形库的原因,包括代码简洁、控件丰富和界面美观,并分享了在Windows环境下通过MSYS2安装GTK4及在CLion中配置开发环境的详细步骤。
977 0
|
11月前
|
SQL Go 数据库
Gorm使用教程:掌握高级查询的技巧。
以上就是我们今天的旅程中所会遇到的一些有趣的Gorm查询技巧。学习这些技巧像是学着驾驶一辆全新的巴士,只要你掌握了这些,你可以在数据库的海洋中自由驾驶,轻松地转向,畅游其中。祝你在Gorm的世界中探索愉快!
300 36
|
存储 SQL 弹性计算
元数据驱动的 SaaS 架构与背后的技术思考
在抽象能力以及沉淀了产品的基础上,把所承载和沉淀的业务能力快速输出,贡献给整个行业。
10764 114
元数据驱动的 SaaS 架构与背后的技术思考
|
NoSQL 前端开发 Redis
Windows 下安装和配置 Redis (图文教程)
Windows 下安装和配置 Redis (图文教程)
|
Java 应用服务中间件 Spring
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
636 5
|
存储 Go 开发者
在Go中对切片/数组求和的多种方法
在Go中对切片/数组求和的多种方法
|
Sentinel
一文速通Sentinel熔断及降级规则
一文速通Sentinel熔断及降级规则
|
SQL 关系型数据库 MySQL
【GORM】使用GORM连接各种数据库
1.概述 gorm是一个使用Go语言编写的ORM框架。它文档齐全,对开发者友好,支持主流数据库。
1732 0