Golang Go语言中 Gorm 2.0 是否支持全局的 BeforeSave 钩子函数

发布于 1周前 作者 ionicwang 来自 Go语言

问题:
求告诉全局注册钩子的范例

go<br>type UserInfo struct {<br> <a target="_blank" href="http://fmkModel.ID" rel="nofollow noopener">fmkModel.ID</a><br> Name string `json:"name" gorm:"not null;comment:用户名称"`<br> Mobile string `json:"mobile" gorm:"not null;index;comment:用户手机号"`<br> Password string `json:"password" gorm:"not null;default:'';comment:用户密码"`<br> fmkModel.CreateUpdate<br> fmkModel.SoftDeletes<br>}<br><br>type CreateUpdate struct {<br> CreatedBy uint `json:"created_by"`<br> CreatedTime time.Time `json:"created_time"`<br> UpdatedBy uint `json:"updated_by"`<br> UpdatedTime time.Time `json:"updated_time"`<br>}<br><br><br>注册全局 hook<br>DB.Callback().Create().Before("gorm:before_save").Register("my:before_save", bootstrap.MyBeforeSaveHook)<br><br>func MyBeforeSaveHook(db *gorm.DB) {<br> statement := db.Statement<br> setGormCreateTime(statement, nowTime)<br>}<br><br>func setGormCreateTime(statement *gorm.Statement, nowTime time.Time) {<br> dest := statement.Dest<br><br> value := reflect.ValueOf(dest)<br> //value &amp;{{0 0001-01-01 00:00:00 +0000 UTC 0 0001-01-01 00:00:00 +0000 UTC} 111111}<br> fmt.Println("setGormCreateTime value ", value)<br> valueElem := value.Elem()<br> //valueElem {{0 0001-01-01 00:00:00 +0000 UTC 0 0001-01-01 00:00:00 +0000 UTC} 111111}<br> fmt.Println("setGormCreateTime valueElem ", valueElem)<br><br> createUpdateField := valueElem.FieldByName("CreateUpdate")<br> if !createUpdateField.IsValid() {<br> fmt.Println("setGormCreateTime createUpdateValue 是不合法的")<br> return<br> }<br> fmt.Println("setGormCreateTime createUpdateValue ", createUpdateField.Kind())<br> if reflect.Struct != createUpdateField.Kind() {<br> return<br> }<br> createdTimeField := createUpdateField.FieldByName("CreatedTime")<br> // Check if the CreatedTime field is valid and can be set<br> if createdTimeField.IsValid() &amp;&amp; createdTimeField.CanSet() {<br> // Modify the CreatedTime value<br> //createdTimeField.Set(reflect.ValueOf(newTime))<br> statement.SetColumn("CreatedTime", nowTime)<br> }<br>}<br><br><br>

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

sql<br><br>[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)<br>[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<br><br><br>
Golang Go语言中 Gorm 2.0 是否支持全局的 BeforeSave 钩子函数


更多关于Golang Go语言中 Gorm 2.0 是否支持全局的 BeforeSave 钩子函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

我尝试一下方案,也失败了。

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

更多关于Golang Go语言中 Gorm 2.0 是否支持全局的 BeforeSave 钩子函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


不太懂这个用法哈,我平时用的 pgsql ,Gorm 原始支持 time.Time 存为 timestampz 或者时间戳,你着同时定义CreatedByCreatedTime的意义在哪?

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

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

你还用到了Register方法,这个不属于钩子了,这个是用于插件的
https://gorm.io/zh_CN/docs/write_plugins.html


按照官方的示例写,一个对方一个 hook 钩子也是 ok 的,但是重复代码太多了。

所以我想全局的使用他,

我 debug 模式下,可以通过反射的方式,为 CreatedTime updateTime 赋值当前时间,但是无法成功保存

我看到了 plugin ,感谢回复。

在Golang的Gorm 2.0中,确实支持全局的BeforeSave钩子函数。Gorm的钩子功能允许你在模型的CRUD(创建、读取、更新、删除)操作之前或之后自动执行一些代码,这对于日志记录、数据验证、自动填充字段等场景非常有用。

对于全局钩子,你可以在初始化Gorm数据库连接时,通过调用Callback().Create().Before("gorm:create")Callback().Update().Before("gorm:update")来注册一个全局的BeforeSave钩子。需要注意的是,Gorm 2.0中的全局钩子会影响所有模型,因此在使用时需要谨慎,确保它不会引入意外的副作用。

例如,要注册一个全局的BeforeSave钩子,可以这样做:

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
    panic("failed to connect database")
}

db.Callback().Create().Before("gorm:create").Register("my_before_save_hook", func(db *gorm.DB) {
    // 在这里编写你的BeforeSave逻辑
    fmt.Println("Before Save Hook Called")
})

db.Callback().Update().Before("gorm:update").Register("my_before_update_hook", func(db *gorm.DB) {
    // 在这里编写你的BeforeSave逻辑(针对更新操作)
})

这样,每当有模型被创建或更新时,相应的钩子函数就会被调用。通过这种方式,你可以为所有模型提供一致的预处理逻辑。

回到顶部