Object Life Cycle

Hooks are functions that are called before or after creation/querying/updating/deletion.

If you have defined specified methods for a model, it will be called automatically when creating, updating, querying, deleting, and if any callback returns an error, GORM will stop future operations and rollback current transaction.

The type of hook methods should be func(*gorm.DB) error

Hooks

Creating an object

Available hooks for creating

  1. // begin transaction
  2. BeforeSave
  3. BeforeCreate
  4. // save before associations
  5. // insert into database
  6. // save after associations
  7. AfterCreate
  8. AfterSave
  9. // commit or rollback transaction

Code Example:

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

NOTE Save/Delete operations in GORM are running in transactions by default, so changes made in that transaction are not visible until it is committed, if you return any error in your hooks, the change will be rollbacked

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

Updating an object

Available hooks for updating

  1. // begin transaction
  2. BeforeSave
  3. BeforeUpdate
  4. // save before associations
  5. // update database
  6. // save after associations
  7. AfterUpdate
  8. AfterSave
  9. // commit or rollback transaction

Code Example:

  1. func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
  2. if u.readonly() {
  3. err = errors.New("read only user")
  4. }
  5. return
  6. }
  7. // Updating data in same transaction
  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. }

Deleting an object

Available hooks for deleting

  1. // begin transaction
  2. BeforeDelete
  3. // delete from database
  4. AfterDelete
  5. // commit or rollback transaction

Code Example:

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

Querying an object

Available hooks for querying

  1. // load data from database
  2. // Preloading (eager loading)
  3. AfterFind

Code Example:

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

Modify current operation

  1. func (u *User) BeforeCreate(tx *gorm.DB) error {
  2. // Modify current operation through tx.Statement, e.g:
  3. tx.Statement.Select("Name", "Age")
  4. tx.Statement.AddClause(clause.OnConflict{DoNothing: true})
  5. // tx is new session mode with the `NewDB` option
  6. // operations based on it will run inside same transaction but without any current conditions
  7. var role Role
  8. err := tx.First(&role, "name = ?", user.Role).Error
  9. // SELECT * FROM roles WHERE name = "admin"
  10. // ...
  11. return err
  12. }