从未调用过 BeforeUpdate 钩子

时间:2020-12-18 18:01:54

标签: go go-gorm

我正在使用 gorm.io 库,版本 1.20.8,目前可用的最后一个。 我有这个简化的模型:

type ExternalUser struct {
    BaseModel
    Name            string `gorm:"type:char(255);uniqueIndex:compositeIndex;not null"`
    Password        string
    HashPassword    string
}

使用这个 BeforeUpdate 函数

func (user *ExternalUser) BeforeUpdate(tx *gorm.DB) error {
        pass, _ := utils.HashPassword(user.Password)
        tx.Statement.SetColumn("HashPassword", pass)
        encryptedPass := utils.EncryptString(user.Password)
        tx.Statement.SetColumn("Password", encryptedPass)
    return nil
}

但它似乎从未被调用过,我不明白为什么。 这是我调用的更新函数:

func UpdateExternalUser(dataForm command.ExternalUserUpdate, externalUserID string, userId uuid.UUID) (int64, error) {
    dataForm.UpdatedUserID = userId
    result := database.DB().Table("external_user").Where("id=?", externalUserID).Updates(&dataForm)
    if err := result.Error; err != nil {
        return -1, err
    }
    row := result.RowsAffected
    return row, nil
}

BeforeCreate 钩子工作正常。

上面模型中的 BaseModel 类型定义如下:

type BaseModel struct {
    ID            uuid.UUID `gorm:"type:char(36);primary_key;"`
    Version       int64     `gorm:"not null;"`
    CreatedAt     time.Time `gorm:"index;"`
    UpdatedAt     time.Time `gorm:"index;"`
    CreatedUserID uuid.UUID `gorm:"type:char(36);index;not null;"`
    UpdatedUserID uuid.UUID `gorm:"type:char(36);index;not null;"`
}

func (BaseModel *BaseModel) BeforeCreate(tx *gorm.DB) error {
    newUUID := uuid.NewV4()
    tx.Statement.SetColumn("ID", newUUID)
    tx.Statement.SetColumn("Version", 0)
    return nil
}

更新

作为评论指出,我将查询更改如下:

result := database.DB().Model(&model.ExternalUser{}).Where("id=?", externalUserID).Updates(&dataForm)

现在确实发生了钩子,但是我遇到了一个恐慌错误,我想是因为我传递的模型结构 Model(&model.ExternalUser{}) 是空的。

这里是传递的错误信息:

2020/12/18 20:31:32 [Recovery] 2020/12/18 - 20:31:32 panic recovered:
PUT /core/api/v1/external-user/4dd6223f-0546-4e20-a6e1-9cd89499b281 HTTP/1.1
Host: localhost:8090
Accept: */*
Accept-Encoding: gzip, deflate, br
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 407
Content-Type: application/json
Postman-Token: 9844ea91-5e25-4123-a950-0a19f80352a1
Uber-Trace-Id: 77b3baa8890e5788:7ada969a1b89b7e5:77b3baa8890e5788:1
User-Agent: PostmanRuntime/7.26.8


reflect: call of reflect.Value.Field on string Value
/usr/local/go/src/reflect/value.go:850 (0x411ac04)
        Value.Field: panic(&ValueError{"reflect.Value.Field", v.kind()})
/Users/xxxx/Project/go/pkg/mod/gorm.io/gorm@v1.20.8/schema/field.go:393 (0x4a41a93)
        (*Field).setupValuerAndSetter.func2: fieldValue := reflect.Indirect(value).Field(field.StructField.Index[0]).Field(field.StructField.Index[1])
/Users/xxxx/Project/go/pkg/mod/gorm.io/gorm@v1.20.8/callbacks/update.go:230 (0x4ae6f74)
        ConvertToAssignments: value, isZero := field.ValueOf(updatingValue)
/Users/xxxx/Project/go/pkg/mod/gorm.io/driver/mysql@v1.0.3/update_with_order_by_limit.go:20 (0x4aeeef2)
        Update: if set := callbacks.ConvertToAssignments(db.Statement); len(set) != 0 {
/Users/xxxx/Project/go/pkg/mod/gorm.io/gorm@v1.20.8/callbacks.go:105 (0x4a56f33)
        (*processor).Execute: f(db)
/Users/xxxx/Project/go/pkg/mod/gorm.io/gorm@v1.20.8/finisher_api.go:318 (0x4a61a27)
        (*DB).Updates: tx.callbacks.Update().Execute(tx)

更新/2

经过一些测试后,我发现使用这条线一切正常:

result := database.DB().Model(&model.ExternalUser{}).Where("id = ?", externalUserID).Updates(model.ExternalUser{Name: dataForm.Name, Password: dataForm.Password})

但在这种情况下,我被迫在更新条款中指定每个字段,而不是只传递结构。

0 个答案:

没有答案