Hooks

物件生命週期

Hooks 是在建立/查詢/更新/刪除之前或之後呼叫的函式。

如果您已為模型定義特定方法,它將在建立、更新、查詢、刪除時自動呼叫,且如果任何回呼傳回錯誤,GORM 將停止後續作業並回滾目前的交易。

Hook 方法的類型應為 func(*gorm.DB) error

Hooks

建立物件

可用的建立 Hook

// begin transaction
BeforeSave
BeforeCreate
// save before associations
// insert into database
// save after associations
AfterCreate
AfterSave
// commit or rollback transaction

程式碼範例

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 中的儲存/刪除作業預設以交易方式執行,因此在交易中所做的變更在提交前都不可見,如果您在 Hook 中傳回任何錯誤,變更將會回滾

func (u *User) AfterCreate(tx *gorm.DB) (err error) {
if !u.IsValid() {
return errors.New("rollback invalid user")
}
return nil
}

更新物件

可用的更新 Hook

// begin transaction
BeforeSave
BeforeUpdate
// save before associations
// update database
// save after associations
AfterUpdate
AfterSave
// commit or rollback transaction

程式碼範例

func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
if u.readonly() {
err = errors.New("read only user")
}
return
}

// Updating data in same transaction
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

// begin transaction
BeforeDelete
// delete from database
AfterDelete
// commit or rollback transaction

程式碼範例

// Updating data in same transaction
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

// load data from database
// 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 {
// Modify current operation through tx.Statement, e.g:
tx.Statement.Select("Name", "Age")
tx.Statement.AddClause(clause.OnConflict{DoNothing: true})

// tx is new session mode with the `NewDB` option
// operations based on it will run inside same transaction but without any current conditions
var role Role
err := tx.First(&role, "name = ?", user.Role).Error
// SELECT * FROM roles WHERE name = "admin"
// ...
return err
}

白金贊助商

金牌贊助商

白金贊助商

金牌贊助商