V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
RedBeanIce
V2EX  ›  Go 编程语言

golang Gorm 2.0 是否支持全局的 BeforeSave 钩子函数?我尝试了许多情况,以下是其中一次尝试的概述,但未成功。SQL 日期仍然保持为'0000-00-00'。

  •  
  •   RedBeanIce · 2023-12-08 01:11:10 +08:00 · 1180 次点击
    这是一个创建于 386 天前的主题,其中的信息可能已经有所发展或是发生改变。
    问题:
    求告诉全局注册钩子的范例

    ```go
    type UserInfo struct {
    fmkModel.ID
    Name string `json:"name" gorm:"not null;comment:用户名称"`
    Mobile string `json:"mobile" gorm:"not null;index;comment:用户手机号"`
    Password string `json:"password" gorm:"not null;default:'';comment:用户密码"`
    fmkModel.CreateUpdate
    fmkModel.SoftDeletes
    }

    type CreateUpdate struct {
    CreatedBy uint `json:"created_by"`
    CreatedTime time.Time `json:"created_time"`
    UpdatedBy uint `json:"updated_by"`
    UpdatedTime time.Time `json:"updated_time"`
    }


    注册全局 hook
    DB.Callback().Create().Before("gorm:before_save").Register("my:before_save", bootstrap.MyBeforeSaveHook)

    func MyBeforeSaveHook(db *gorm.DB) {
    statement := db.Statement
    setGormCreateTime(statement, nowTime)
    }

    func setGormCreateTime(statement *gorm.Statement, nowTime time.Time) {
    dest := statement.Dest

    value := reflect.ValueOf(dest)
    //value &{{0 0001-01-01 00:00:00 +0000 UTC 0 0001-01-01 00:00:00 +0000 UTC} 111111}
    fmt.Println("setGormCreateTime value ", value)
    valueElem := value.Elem()
    //valueElem {{0 0001-01-01 00:00:00 +0000 UTC 0 0001-01-01 00:00:00 +0000 UTC} 111111}
    fmt.Println("setGormCreateTime valueElem ", valueElem)

    createUpdateField := valueElem.FieldByName("CreateUpdate")
    if !createUpdateField.IsValid() {
    fmt.Println("setGormCreateTime createUpdateValue 是不合法的")
    return
    }
    fmt.Println("setGormCreateTime createUpdateValue ", createUpdateField.Kind())
    if reflect.Struct != createUpdateField.Kind() {
    return
    }
    createdTimeField := createUpdateField.FieldByName("CreatedTime")
    // Check if the CreatedTime field is valid and can be set
    if createdTimeField.IsValid() && createdTimeField.CanSet() {
    // Modify the CreatedTime value
    //createdTimeField.Set(reflect.ValueOf(newTime))
    statement.SetColumn("CreatedTime", nowTime)
    }
    }


    ```

    经过如上的尝试,我看到时间已经改变了。但是 sql 执行仍然出现了错误。

    ```sql

    [5567.310ms] [rows:0] INSERT INTO `user_info` (`name`,`mobile`,`password`,`created_by`,`created_time`,`updated_by`,`updated_time`,`del_flag`) VALUES ('张三','18000855903','$2a$04$VfAU4pidT6wI6llBQKT1GuEcd2bmFfnbuSu.YprgXHYwA7Nl5FoJ.',0,'0000-00-00 00:00:00',0,'0000-00-00 00:00:00',0)
    [2023-12-08 01:01:05.427] local.error controller/userInfoController.go:21 Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'created_time' at row 1


    ```
    5 条回复    2023-12-08 09:08:46 +08:00
    RedBeanIce
        1
    RedBeanIce  
    OP
       2023-12-08 01:24:44 +08:00
    我尝试一下方案,也失败了。

    ```

    sch := db.Statement.Schema
    value, ok := sch.FieldsByDBName["created_time"]
    if ok {
    fieldType := value.FieldType.String()
    if fieldType == "time.Time" {
    err := value.Set(db.Statement.Context, db.Statement.ReflectValue, time.Now())
    if err != nil {
    return
    }
    }
    }



    ```
    TossPig
        2
    TossPig  
       2023-12-08 08:52:26 +08:00   ❤️ 1
    不太懂这个用法哈,我平时用的 pgsql ,Gorm 原始支持 time.Time 存为 timestampz 或者时间戳,你着同时定义`CreatedBy`和`CreatedTime`的意义在哪?

    看你的报错应该是生成的 sql 语法错误

    官方文档提供的例子是没问题的 https://gorm.io/zh_CN/docs/hooks.html

    你还用到了`Register`方法,这个不属于钩子了,这个是用于插件的
    https://gorm.io/zh_CN/docs/write_plugins.html
    RedBeanIce
        3
    RedBeanIce  
    OP
       2023-12-08 09:05:23 +08:00
    @TossPig
    按照官方的示例写,一个对方一个 hook 钩子也是 ok 的,但是重复代码太多了。

    所以我想全局的使用他,

    我 debug 模式下,可以通过反射的方式,为 CreatedTime updateTime 赋值当前时间,但是`无法成功保存`。
    RedBeanIce
        5
    RedBeanIce  
    OP
       2023-12-08 09:08:46 +08:00
    @TossPig 我看到了 plugin ,感谢回复。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1165 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:28 · PVG 02:28 · LAX 10:28 · JFK 13:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.