1. 钩子

1.1. 对象的生命周期

钩子是一个在 插入/查询/更新/删除 之前或之后被调用的方法。

如果你在一个模型中定义了特殊的方法,它将会在插入,更新,查询,删除的时候被自动调用,如果任何的回调抛出错误,GORM 将会停止将要执行的操作并且回滚当前的改变。

1.2. 钩子

1.2.1. 创建一个对象

可用于创建的钩子

  1. // 开启事务
  2. BeforeSave
  3. BeforeCreate
  4. // 连表前的保存
  5. // 更新时间戳 `CreatedAt`, `UpdatedAt`
  6. // 保存自己
  7. // 重载哪些有默认值和空的字段
  8. // 链表后的保存
  9. AfterCreate
  10. AfterSave
  11. // 提交或回滚事务

代码例子:

  1. func (u *User) BeforeSave() (err error) {
  2. if u.IsValid() {
  3. err = errors.New("can't save invalid data")
  4. }
  5. return
  6. }
  7. func (u *User) AfterCreate(scope *gorm.Scope) (err error) {
  8. if u.ID == 1 {
  9. scope.DB().Model(u).Update("role", "admin")
  10. }
  11. return
  12. }

注意,在 GORM 中的保存/删除 操作会默认进行事务处理,所以在事物中,所有的改变都是无效的,直到它被提交为止:

  1. func (u *User) AfterCreate(tx *gorm.DB) (err error) {
  2. tx.Model(u).Update("role", "admin")
  3. return
  4. }

1.2.2. 更新一个对象

可用于更新的钩子

  1. // 开启事务
  2. BeforeSave
  3. BeforeUpdate
  4. // 链表前的保存
  5. // 更新时间戳 `UpdatedAt`
  6. // 保存自身
  7. // 链表后的保存
  8. AfterUpdate
  9. AfterSave
  10. // 提交或回滚的事务

代码示例:

  1. func (u *User) BeforeUpdate() (err error) {
  2. if u.readonly() {
  3. err = errors.New("read only user")
  4. }
  5. return
  6. }
  7. // 在事务结束后,进行更新数据
  8. func (u *User) AfterUpdate(tx *gorm.DB) (err error) {
  9. if u.Confirmed {
  10. tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("verfied", true)
  11. }
  12. return
  13. }

1.2.3. 删除一个对象

可用于删除的钩子

  1. // 开启事务
  2. BeforeDelete
  3. // 删除自身
  4. AfterDelete
  5. // 提交或回滚事务

代码示例:

  1. // 在事务结束后进行更新数据
  2. func (u *User) AfterDelete(tx *gorm.DB) (err error) {
  3. if u.Confirmed {
  4. tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("invalid", false)
  5. }
  6. return
  7. }

1.2.4. 查询一个对象

可用于查询的钩子

  1. // 从数据库中读取数据
  2. // 加载之前 (急于加载)
  3. AfterFind

代码示例:

  1. func (u *User) AfterFind() (err error) {
  2. if u.MemberShip == "" {
  3. u.MemberShip = "user"
  4. }
  5. return
  6. }