GORM 删除钩子实现
本文介绍 GORM 中删除操作的钩子函数实现方法。
钩子方法
BeforeDelete
在记录删除之前执行,常用于删除前的校验和关联数据处理。
Go
type Order struct {
ID uint
UserID uint
Status string
}
// 删除前校验订单状态
func (o *Order) BeforeDelete(tx *gorm.DB) error {
if o.Status == "paid" {
return errors.New("已支付订单不能删除")
}
return nil
}
BeforeDelete 返回 error 时,删除操作会被中止并回滚事务。
AfterDelete
在记录删除之后执行,常用于清理关联数据或记录删除日志。
Go
type User struct {
ID uint
Name string
}
// 删除后清理关联数据
func (u *User) AfterDelete(tx *gorm.DB) error {
// 清理关联订单
err := tx.Where("user_id = ?", u.ID).Delete(&Order{}).Error
if err != nil {
return err
}
// 记录删除日志
log.Printf("用户 %d (%s) 已被删除", u.ID, u.Name)
return nil
}
钩子方法签名
Go
// 删除前钩子
func (model *ModelName) BeforeDelete(tx *gorm.DB) error
// 删除后钩子
func (model *ModelName) AfterDelete(tx *gorm.DB) error
软删除与钩子
Go
type Post struct {
ID uint
Title string
DeletedAt gorm.DeletedAt `gorm:"index"`
}
// 软删除时同样触发钩子
func (p *Post) BeforeDelete(tx *gorm.DB) error {
// 软删除前校验
if p.Title == "" {
return errors.New("标题为空的帖子不能删除")
}
return nil
}
func (p *Post) AfterDelete(tx *gorm.DB) error {
// 软删除后更新缓存
return clearPostCache(p.ID)
}
使用
gorm.DeletedAt字段时,Delete 方法执行的是软删除,钩子同样会被触发。
注意事项
- Delete 方法触发 BeforeDelete/AfterDelete 钩子。
- 批量删除时,钩子会对每条记录分别执行(若逐条删除)。
db.Unscoped().Delete()执行硬删除,同样触发钩子。- BeforeDelete 返回 error 会中止并回滚;AfterDelete 返回 error 仅记录日志(软删除已生效)。
- 关联删除(如
Select/Constraint)不触发关联模型的删除钩子,仅在模型自身调用 Delete 时触发。
要点总结
- BeforeDelete在删除前执行,适合权限校验和业务规则检查。
- AfterDelete在删除后执行,适合清理关联数据或记录日志。
- 软删除(
DeletedAt)和硬删除(Unscoped)都会触发删除钩子。 - 批量删除时钩子逐条执行,需注意性能影响。
- 关联级联删除不会触发关联模型的删除钩子,仅主模型钩子生效。
存放路径:D:\git2\jwdev\articles\GORM\进阶\钩子函数与回调机制\删除钩子实现.md
📝 发现内容有误?点击此处直接编辑