-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbulk_create.go
80 lines (68 loc) · 1.83 KB
/
bulk_create.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package gormhelper
import (
"context"
"gorm.io/gorm"
"gorm.io/gorm/schema"
"reflect"
"strings"
)
// BulkCreate 批量创建
func BulkCreate[T Model](db *gorm.DB, ctx context.Context, data []*T, batchSize int, opts ...Option) (err error) {
if len(data) == 0 {
return nil
}
options := NewOptions(opts...)
tableName := GetTableName[T]()
columns, placeholders := getColumnsAndPlaceholders(data[0])
for i := 0; i < len(data); i += batchSize {
end := i + batchSize
if end > len(data) {
end = len(data)
}
sql := "INSERT "
if options.Ignore {
sql += "IGNORE "
}
sql += "INTO " + tableName + " (" + columns + ") VALUES "
var values []interface{}
for _, record := range data[i:end] {
sql += "(" + placeholders + "),"
values = append(values, getValues(record)...)
}
sql = sql[:len(sql)-1] // 去掉最后一个逗号
if err = db.WithContext(ctx).Exec(sql, values...).Error; err != nil {
return err
}
}
return nil
}
// 获取数据的列名和占位符
func getColumnsAndPlaceholders[T Model](data *T) (string, string) {
val := reflect.ValueOf(data).Elem()
numFields := val.NumField()
columns := make([]string, numFields)
placeholders := make([]string, numFields)
for i := 0; i < numFields; i++ {
placeholders[i] = "?"
field := val.Type().Field(i)
if tag, ok := field.Tag.Lookup("gorm"); ok {
tagSettings := schema.ParseTagSetting(tag, ";")
var column string
if column, ok = tagSettings["COLUMN"]; ok {
columns[i] = column
continue
}
}
columns[i] = field.Name
}
return strings.Join(columns, ", "), strings.Join(placeholders, ", ")
}
// 获取数据的值
func getValues[T Model](data *T) []interface{} {
val := reflect.ValueOf(data).Elem()
values := make([]interface{}, val.NumField())
for i := 0; i < val.NumField(); i++ {
values[i] = val.Field(i).Interface()
}
return values
}