对象生命周期
Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。
如果您已经为模型定义了指定的方法,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务。
钩子方法的函数签名应该是 func(*gorm.DB) error
Hook
创建对象
创建时可用的 hook
// 开始事务BeforeSaveBeforeCreate// 关联前的 save// 插入记录至 db// 关联后的 saveAfterCreateAfterSave// 提交或回滚事务
代码示例:
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {u.UUID = uuid.New()if !u.IsValid() {err = errors.New("can't save invalid data")}return}func (u *User) AfterCreate(tx *gorm.DB) (err error) {if u.ID == 1 {tx.Model(u).Update("role", "admin")}return}
注意 在 GORM 中保存、删除操作会默认运行在事务上, 因此在事务完成之前该事务中所作的更改是不可见的,如果您的钩子返回了任何错误,则修改将被回滚。
func (u *User) AfterCreate(tx *gorm.DB) (err error) {if !u.IsValid() {return errors.New("rollback invalid user")}return nil}
更新对象
更新时可用的 hook
// 开始事务BeforeSaveBeforeUpdate// 关联前的 save// 更新 db// 关联后的 saveAfterUpdateAfterSave// 提交或回滚事务
代码示例:
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {if u.readonly() {err = errors.New("read only user")}return}// 在同一个事务中更新数据func (u *User) AfterUpdate(tx *gorm.DB) (err error) {if u.Confirmed {tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("verfied", true)}return}
删除对象
删除时可用的 hook
// 开始事务BeforeDelete// 删除 db 中的数据AfterDelete// 提交或回滚事务
代码示例:
// 在同一个事务中更新数据func (u *User) AfterDelete(tx *gorm.DB) (err error) {if u.Confirmed {tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("invalid", false)}return}
查询对象
查询时可用的 hook
// 从 db 中加载数据// Preloading (eager loading)AfterFind
代码示例:
func (u *User) AfterFind(tx *gorm.DB) (err error) {if u.MemberShip == "" {u.MemberShip = "user"}return}
修改当前操作
func (u *User) BeforeCreate(tx *gorm.DB) error {// 通过 tx.Statement 修改当前操作,例如:tx.Statement.Select("Name", "Age")tx.Statement.AddClause(clause.OnConflict{DoNothing: true})// tx 是带有 `NewDB` 选项的新会话模式// 基于 tx 的操作会在同一个事务中,但不会带上任何当前的条件err := tx.First(&role, "name = ?", user.Role).Error// SELECT * FROM roles WHERE name = "admin"// ...return err}