douyu/jupiter

create方法传入slice报Error: reflect: call of reflect.Value.Interface on zero Value

movekj opened this issue · 4 comments

包版本

github.com/douyu/jupiter v0.4.7
github.com/jinzhu/gorm v1.9.16

业务代码

newPlayBookTasks := []*task_model.PlayBookTask{}

for _, playBookTask := range playBookTasks {
newPlayBookTasks = append(newPlayBookTasks, &task_model.PlayBookTask{
	TaskId:     playBookTask.TaskId,
	PlayBookId: playBookTask.PlayBookId,
	PreTaskId:  playBookTask.PlayBookId,
	NextTaskId: playBookTask.NextTaskId,
})
}
fmt.Println(newPlayBookTasks)
result := orm.DB.Create(&newPlayBookTasks)

堆栈报错信息

/home/lixingxing/go/pkg/mod/github.com/jinzhu/gorm@v1.9.16/scope.go in (*Scope).callCallbacks.func1 at line 865

	defer func() {
		if err := recover(); err != nil {
			if db, ok := scope.db.db.(sqlTx); ok {
				db.Rollback()
			}
			panic(err)
		}
	}()
	for _, f := range funcs {
		(*f)(scope)
		if scope.skipLeft {
Called from: /usr/local/go1.19.2/src/reflect/value.go in valueInterface
/home/lixingxing/go/pkg/mod/github.com/jinzhu/gorm@v1.9.16/callback_create.go in createCallback at line 68

					if field.IsBlank && field.HasDefaultValue {
						blankColumnsWithDefaultValue = append(blankColumnsWithDefaultValue, scope.Quote(field.DBName))
						scope.InstanceSet("gorm:blank_columns_with_default_value", blankColumnsWithDefaultValue)
					} else if !field.IsPrimaryKey || !field.IsBlank {
						columns = append(columns, scope.Quote(field.DBName))
						placeholders = append(placeholders, scope.AddToVars(field.Field.Interface()))
					}
				} else if field.Relationship != nil && field.Relationship.Kind == "belongs_to" {
					for _, foreignKey := range field.Relationship.ForeignDBNames {
						if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) {
							columns = append(columns, scope.Quote(foreignField.DBName))
/home/lixingxing/go/pkg/mod/github.com/douyu/jupiter@v0.4.7/pkg/store/gorm/interceptor.go in debugInterceptor.func1.1 at line 39

func debugInterceptor(dsn *DSN, op string, options *Config) func(Handler) Handler {
	return func(next Handler) Handler {
		return func(scope *Scope) {
			fmt.Printf("%-50s[%s] => %s\n", xcolor.Green(dsn.Addr+"/"+dsn.DBName), time.Now().Format("04:05.000"), xcolor.Green("Send: "+logSQL(scope.SQL, scope.SQLVars, true)))
			next(scope)
			if scope.HasError() {
				fmt.Printf("%-50s[%s] => %s\n", xcolor.Red(dsn.Addr+"/"+dsn.DBName), time.Now().Format("04:05.000"), xcolor.Red("Erro: "+scope.DB().Error.Error()))
			} else {
				fmt.Printf("%-50s[%s] => %s\n", xcolor.Green(dsn.Addr+"/"+dsn.DBName), time.Now().Format("04:05.000"), xcolor.Green("Affected: "+strconv.Itoa(int(scope.DB().RowsAffected))))
			}
/home/lixingxing/go/pkg/mod/github.com/douyu/jupiter@v0.4.7/pkg/store/gorm/interceptor.go in traceInterceptor.func1.1 at line 120

					span.SetTag("peer.statement", logSQL(scope.SQL, scope.SQLVars, options.DetailSQL))
					return
				}
			}
			next(scope)
		}
	}
}
/home/lixingxing/go/pkg/mod/github.com/douyu/jupiter@v0.4.7/pkg/store/gorm/interceptor.go in metricInterceptor.func1.1 at line 53

func metricInterceptor(dsn *DSN, op string, options *Config) func(Handler) Handler {
	return func(next Handler) Handler {
		return func(scope *Scope) {
			beg := time.Now()
			next(scope)
			cost := time.Since(beg)
			// error metric
			if scope.HasError() {
				metric.LibHandleCounter.WithLabelValues(metric.TypeGorm, dsn.DBName+"."+scope.TableName(), dsn.Addr, "ERR").Inc()
/home/lixingxing/go/pkg/mod/github.com/jinzhu/gorm@v1.9.16/scope.go in (*Scope).callCallbacks at line 869

			}
			panic(err)
		}
	}()
	for _, f := range funcs {
		(*f)(scope)
		if scope.skipLeft {
			break
		}
	}
	return scope
/home/lixingxing/go/pkg/mod/github.com/jinzhu/gorm@v1.9.16/main.go in (*DB).Create at line 483

}
// Create insert the value into database
func (s *DB) Create(value interface{}) *DB {
	scope := s.NewScope(value)
	return scope.callCallbacks(s.parent.callbacks.creates).db
}
// Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition
// WARNING If model has DeletedAt field, GORM will only set field DeletedAt's value to current time
func (s *DB) Delete(value interface{}, where ...interface{}) *DB {
/home/lixingxing/thor/internal/apps/task/service/task.go in ClonePlayBook at line 817

			PreTaskId:  playBookTask.PlayBookId,
			NextTaskId: playBookTask.NextTaskId,
		})
	}
	fmt.Println(newPlayBookTasks)
	result := orm.DB.Create(newPlayBookTasks)
	// result := orm.DB.Save(&newPlayBook)
	err = result.Error
	return
}

gorm这个版本不支持批量插入吧

官方文档上面create方法可以传入slice

gorm这个版本不支持批量插入吧

github.com/jinzhu/gorm是v1的gorm,不支持批量插入,需要v2版本才支持,也就是github.com/go-gorm/gorm

Stale issue message