在go语言中使用gorm批量插入数据库代码示例
Go  /  管理员 发布于 1年前   353
go + gorm利用反射机制获取数据集的类型和字段,合生批量插入的 sql,最终利用 exec 语句执行。
示例代码:
// BatchCreate 批量插入
func BatchCreate(db *gorm.DB, data interface{}) error {
getValue := reflect.ValueOf(data)
if getValue.Kind() != reflect.Slice {
return errors.New("数据类型不支持")
}
l := getValue.Len()
if l == 0 {
return nil
}
firstValue := getValue.Index(0)
fieldNum := firstValue.NumField()
tableName := getTableName(firstValue.Type().Name())
const CreatedAt = "CreatedAt" //创建时间的结构体字段名
const UpdatedAt = "UpdatedAt" //更新时间的结构体字段名
const CreatedAtField = "created_at" //创建时间的数据库字段名
const UpdatedAtField = "updated_at" //更新时间的数据库字段名
//获取字段名称
var fields []string
for i := 0; i < fieldNum; i++ {
if firstValue.Field(i).Type().String() == "gorm.Model" {
gormValue := reflect.ValueOf(firstValue.Field(i).Interface())
for j := 0; j < gormValue.NumField(); j++ {
if gormValue.Type().Field(j).Name == CreatedAt {
fields = append(fields, CreatedAtField)
} else if gormValue.Type().Field(j).Name == UpdatedAt {
fields = append(fields, UpdatedAtField)
}
}
continue
}
column := getTagValues(firstValue.Type().Field(i).Tag.Get("gorm"))["column"]
if column != "" {
fields = append(fields, column)
}
}
//获取字段值
var values []string
for i := 0; i < l; i++ {
value := getValue.Index(i)
var one []string
for j := 0; j < fieldNum; j++ {
if value.Field(j).Type().String() == "gorm.Model" {
gormValue := reflect.ValueOf(firstValue.Field(j).Interface())
for k := 0; k < gormValue.NumField(); k++ {
if gormValue.Type().Field(k).Name == CreatedAt {
createdTime := getField(gormValue.Field(k).Interface(), gormValue.Field(k).Type().String())
if createdTime == "''" {
createdTime = fmt.Sprintf("'%s'", time.Now().Format("2006-01-02 15:04:05"))
}
one = append(one, createdTime)
} else if gormValue.Type().Field(k).Name == UpdatedAt {
updatedTime := getField(gormValue.Field(k).Interface(), gormValue.Field(k).Type().String())
if updatedTime == "''" {
updatedTime = fmt.Sprintf("'%s'", time.Now().Format("2006-01-02 15:04:05"))
}
one = append(one, updatedTime)
}
}
continue
}
if getTagValues(value.Type().Field(j).Tag.Get("gorm"))["column"] != "" {
fieldType := value.Field(j).Type().String()
one = append(one, getField(value.Field(j).Interface(), fieldType))
}
}
values = append(values, fmt.Sprintf("(%s)", strings.Join(one, ",")))
if len(values) >= 100 {
//大于等于100条分页插入
sql := fmt.Sprintf("insert into %s (%s) values%s", tableName, strings.Join(fields, ","), strings.Join(values, ","))
if err := db.Exec(sql).Error; err != nil {
return err
}
values = []string{}
}
}
if len(values) > 0 {
sql := fmt.Sprintf("insert into %s (%s) values%s", tableName, strings.Join(fields, ","), strings.Join(values, ","))
return db.Exec(sql).Error
}
return nil
}
//根据结构体名称获取表名
func getTableName(modelName string) string {
reg, _ := regexp.Compile("[A-Z]([a-z]+)")
return strings.ToLower(strings.Join(reg.FindAllString(modelName, -1), "_"))
}
//获取gorm tag中的字段名
func getTagValues(tag string) map[string]string {
var fieldMap map[string]string
fieldMap = make(map[string]string)
for _, v := range strings.Split(tag, ";") {
s := strings.Split(v, ":")
fieldMap[s[0]] = s[1]
}
return fieldMap
}
//获取插入的字段值
func getField(data interface{}, fieldType string) string {
switch fieldType {
case "string":
return fmt.Sprintf("'%s'", data.(string))
case "uint64":
return fmt.Sprintf("%d", data.(uint64))
case "uint32":
return fmt.Sprintf("%d", data.(uint32))
case "time.Time":
s := data.(time.Time).Format("2006-01-02 15:04:05")
if s == "0001-01-01 00:00:00" {
return "''"
}
return fmt.Sprintf("'%s'", s)
case "*time.Time":
dtime := data.(*time.Time)
if dtime == nil {
return "''"
}
s := dtime.Format("2006-01-02 15:04:05")
if s == "0001-01-01 00:00:00" {
return "''"
}
return fmt.Sprintf("'%s'", s)
}
return "''"
}
gorm model
//gorm.Model
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
type User struct {
gorm.Model
Name string `gorm:"column:name"`
Sex uint32 `gorm:"column:sex"`
}
调用:
users := []User{
{
Name: "小明",
Sex: 0,
},
{
Name: "小红",
Sex: 1,
},
}
BatchCreate(conn, users)
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号