Home >Backend Development >Golang >Is there a way to do BeforeCreate and BeforeUpdate hooks for each structure within a structure?

Is there a way to do BeforeCreate and BeforeUpdate hooks for each structure within a structure?

PHPz
PHPzforward
2024-02-05 21:48:08866browse

有没有办法为结构内的每个结构执行 BeforeCreate 和 BeforeUpdate 挂钩?

Question content

I have the following code:

type innerstructa struct {
 a string
}

type innerstructb struct {
 b string
}

func (a *a) beforecreate(scope *gorm.scope) error {
    return scope.setcolumn("a", uuid.new().string())
}

func (b *b) beforecreate(scope *gorm.scope) error {
    return scope.setcolumn("b", uuid.new().string())
}

type outerstruct struct {
    innerstructa
    innerstructb
    id      string `gorm:"type:varchar(40);not null"`
}

When I create the record:

outerStructObject := OuterStruct{
        ID:          "sample_ID",
    }
err := db.Create(&outerStructObject).Error

Only call one of the beforecreate() hooks. Other beforecreate are skipped.

gorm version is jinzhu/gorm v1.9.16

Is there a way to call both hooks when calling the create statement?

Expected beforecreate hooks to be called for two inner structures - innerstructa and innerstructb.


Correct answer


peter's comment is accurate, I will share my tests and comments here but using the official repositorygo -gorm/ gorm and the latest version v1.25.0 have very similar results and some changes in the api.

When creating an external registry, the internal object can be set like this:

func (o *outerstruct) beforecreate(tx *gorm.db) error {
    fmt.println("hook triggered: beforecreate for outerstruct")
    o.innerstructa.a = uuid.new().string()
    o.innerstructb.b = uuid.new().string()
    return nil
}

To trigger internal object hooks, you can only create them directly:

innera := innerstructa{
    a: "123",
}

errcreateinner := db.create(&innera).error

This is a complete isolated example:

package main

import (
    "fmt"
    "log"

    "github.com/google/uuid"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

func main() {

    db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
    if err != nil {
        panic(err)
    }

    db.AutoMigrate(&InnerStructA{}, &InnerStructB{}, &OuterStruct{})

    outerStructObject := OuterStruct{
        ID: "sample_ID",
    }

    errCreate := db.Create(&outerStructObject).Error
    if err != nil {
        log.Fatal(errCreate)
    }

    var outer OuterStruct
    db.Last(&outer)
    fmt.Println("Last register: ", outer)

    // innerA := InnerStructA{
    //  A: "123",
    // }

    // errCreateInner := db.Create(&innerA).Error
    // if err != nil {
    //  log.Fatal(errCreateInner)
    // }
}

type InnerStructA struct {
    A string
}

type InnerStructB struct {
    B string
}

// This is not being called
func (a *InnerStructA) BeforeCreate(tx *gorm.DB) error {
    fmt.Println("Hook triggered: BeforeCreate for InnerStructA")
    // ...
    return nil
}

// This is not being called
func (b *InnerStructB) BeforeCreate(tx *gorm.DB) error {
    fmt.Println("Hook triggered: BeforeCreate for InnerStructB")
    // ...
    return nil
}

// This works!
func (o *OuterStruct) BeforeCreate(tx *gorm.DB) error {
    fmt.Println("Hook triggered: BeforeCreate for OuterStruct")
    o.InnerStructA.A = uuid.New().String()
    o.InnerStructB.B = uuid.New().String()
    return nil
}

type OuterStruct struct {
    InnerStructA
    InnerStructB
    ID string `gorm:"type:varchar(40);not null"`
}

The above is the detailed content of Is there a way to do BeforeCreate and BeforeUpdate hooks for each structure within a structure?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete