本来应该写Docker的,但是想了下,还是决定先做好开发,最后部署Docker。

 

这里先提出问题,我们models目录下的 tag.go、 article.go 文件,它们有两个方法:AfterCreate、AfterUpdate。

每个文件都要实现这两个办法?

 

目标

通过GORM的 Callbacks 来实现功能,不需要编写每个文件。

功能

  • 每次 create 更新 CreatedOn 字段。
  • 每次 update 更新 ModifiedOn 字段。

 

实现Callbacks

参考文档还是 gorm.io .

参考地址1:https://gorm.io/zh_CN/docs/write_plugins.html

参考地址2:https://gorm.io/docs/update.html#Change-Updating-Values

参考地址3:https://github.com/go-gorm/gorm/issues/3441

参考地址4:https://gorm.io/zh_CN/docs/hooks.html

 

这里我们需要针对 before_create 和 before_update 两个Callback实现

原因可以参考:GORM HOOK章节

 

在models/models.go 文件中增加两个函数:

 

SetColumn函数实际上是GORM包实现的一个辅助函数,内容如下:

 

注册Callback

在 models.go 的 init 函数中增加以下语句:

 

验证

访问AddTag接口,成功之后检查数据库,可以发现 created_on 字段为当前执行时间。

访问EditTag接口,可发现 modified_on 为最后一次执行更新的实际。

 

拓展

P.S. 其实我们实现的 CreatedOn、 ModifiedOn 以及这里要实现的 DeletedOn 都是GORM已经实现好的。

 

实际项目中,硬删除是比较少的,那么是否可以通过Callbacks来完成这个功能呢。

我们在先前 Model struct 增加 DeletedOn 变量。

 

在 init 函数里面替换删除的回调

db.Callback().Delete().Replace(“gorm:delete”, deleteCallback)

 

然后实现 deleteCallback 函数:

P.S. 记得数据库表加上 deleted_on 字段

 

看起来目前实现了一个有bug的版本,不慌,我们可以慢慢修复。

UPDATE blog_tag SET deleted_on=? WHERE id = ?
[1599765813 9]

2020/09/11 03:23:33 /home/xiong/Code/ginBlog/models/models.go:130 sql: expected 2 arguments, got 4
[0.209ms] [rows:0] UPDATE blog_tag SET deleted_on=1599765813 WHERE id = 9

2020/09/11 03:23:33 /home/xiong/Code/ginBlog/models/tag.go:76 sql: expected 2 arguments, got 4
[0.569ms] [rows:0]

 

之前考虑的一种情况是:类型为[]interface {}的变量具有特定的内存布局,在编译时已知:每一个interface{}类型占用两个字(一个用于存储interface包含的类型,另一个用于存储类型的值或指针)。因此,长度为N并且类型为[]interface{}的切片大小为N*2个字长。猜测这是为什么期望两个参数,最终得到四个参数的原因。

说实话我没太理解这里导致的具体问题是什么,去网上搜索了一些,看起来五花八门…

甚至我当时觉得可能问题并不出在db.Exec(db.Statement.SQL.String(), db.Statement.Vars…)这里。

因为当我把对应的SQL、参数拉出来依旧报错。

但是当我把SQL语句放到tag.go文件中,Callback外面时…它神奇的…好了。

 

另一个思路:去看了下源码 Callbacks/delete.go 里面的Delete实现:

理解了这段代码,它主要分为四部分:

  • 获取软删除SQL
  • 获取删除SQL(如果前一步没获取到)
  • 检查WHERE子句
  • 执行SQL

软删除相关的代码在soft_delete.go文件中, 关注一下它的 func (sd SoftDeleteDeleteClause) ModifyStatement(stmt *Statement) 即可。

意味着GORM已经实现好了软删除的流程,我只需要把我需要的代码Copy过来…嘿嘿

 

于是最终版代码:

 

测试了一下软删除,OK了。

 

测试删除

将 models/tag.go 删除标签函数修改:加上了Unscoped()

参考文档:https://gorm.io/zh_CN/docs/delete.html

然后再测试了一下删除:

 

算是搞定了,这里记得把 DeleteTag 函数改回来,不需要 Unscoped() , 这只是我们需要测试一下。

 

小结

我们使用 GORM 完成了创建、更新、删除的Callbacks。

理解了GORM软删除方案。

 

完善软删除需要做的事情如下:

  1. 给Article数据库表增加deleted_on字段
  2. 修改其他代码,增加deleted_on判断

 

附:

一般开发来说,GORM已经实现了 CreatedOn、 ModifiedOn 以及 DeletedOn。

实在是没必要自己实现…我就不继续搞了。

 

【Go】gin Blog项目(八) GORM Callbacks 及拓展
Tagged on:     
0 0 vote
Article Rating
订阅
提醒
2 评论
Newest
Oldest Most Voted
Inline Feedbacks
View all comments

请问,这个软删除之后的查询怎么处理,还要自己写一个callback吗?

Last edited 6 月 之前 by nnn