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

161 天前
 RedBeanIce
问题:
求告诉全局注册钩子的范例

```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


```
968 次点击
所在节点    Go 编程语言
5 条回复
RedBeanIce
161 天前
我尝试一下方案,也失败了。

```

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
160 天前
不太懂这个用法哈,我平时用的 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
160 天前
@TossPig
按照官方的示例写,一个对方一个 hook 钩子也是 ok 的,但是重复代码太多了。

所以我想全局的使用他,

我 debug 模式下,可以通过反射的方式,为 CreatedTime updateTime 赋值当前时间,但是`无法成功保存`。
RedBeanIce
160 天前
RedBeanIce
160 天前
@TossPig 我看到了 plugin ,感谢回复。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/998518

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX