go-gorm / gorm

The fantastic ORM library for Golang, aims to be developer friendly
https://gorm.io
MIT License
37.02k stars 3.94k forks source link

关于在BeforeUpdate钩子函数中执行变更字段的问题 #7170

Open master-nan opened 2 months ago

master-nan commented 2 months ago

Your Question

我在BeforeUpdate钩子函数中有个需求想统一变更修改人字段,于是使用tx.Statement.SetColumn("modify_user", xxx)设置,但是出现了问题

The document you expected this should be explained

追踪了代码发现我调用Updates更新时传入的结构体是精简后的模型,不是表对应的结构体,那他会从Statement下的Model中获取下标,然后去Dest中找这个字段,这可能引发错误,因为我传入的修改结构体可能只是部分字段;当然了如果传入Updates的是map[string]interface{}并不存在这个问题

Expected answer

                    destValue := reflect.ValueOf(stmt.Dest)
        for destValue.Kind() == reflect.Ptr {
            destValue = destValue.Elem()
        }

        if stmt.ReflectValue != destValue {
            if !destValue.CanAddr() {
                destValueCanAddr := reflect.New(destValue.Type())
                destValueCanAddr.Elem().Set(destValue)
                stmt.Dest = destValueCanAddr.Interface()
                destValue = destValueCanAddr.Elem()
            }

            switch destValue.Kind() {
            case reflect.Struct:
                stmt.AddError(field.Set(stmt.Context, destValue, value))
            default:
                stmt.AddError(ErrInvalidData)
            }
        }
        这里的destValue 是不是应该从stmt.Model中得到
                     destValue := reflect.ValueOf(stmt.Model)