gorm批量插入解决方案

我有一个朋友, 最近用gorm发现官方不支持批量插入, 看官方issue 2014年就有人提过这个问题了, 不过现在还不支持
在这里插入图片描述
但是问题不大, 官方留出来一个执行原生SQL(db.Exec)的方法来解决这个问题, 而且官方现在在开发v2版本, 在v2版本中就会支持这个功能了
在这里插入图片描述

但是生活还得继续, bug还是得继续写, 本来想在网上找一个公用方法来维持一下生活, 结果竟然没找见!
此处加震惊
都是指定单个结构体去插入的
在这里插入图片描述
这当然不行了, 写代码的意义不就是为了减轻重复的工作嘛, 既然这样, 就只能自己动手丰衣足食了
在这里插入图片描述

下面为生成语句的方法


// 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里面加就行了

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

在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小僵尸打字员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值