英文:
Is there a way to execute BeforeCreate and BeforeUpdate hooks for every struct inside a struct?
问题
我有以下代码:
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"`
}
当我创建记录时:
outerStructObject := OuterStruct{
ID: "sample_ID",
}
err := db.Create(&outerStructObject).Error
只有一个 BeforeCreate() 钩子被调用。其他 BeforeCreate 被跳过。
Gorm 版本是 jinzhu/gorm v1.9.16
是否有一种方法可以在调用创建语句时同时调用两个钩子?
期望在 InnerStructA 和 InnerStructB 的结构体上都调用 BeforeCreate 钩子。
英文:
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 records:
outerStructObject := OuterStruct{
ID: "sample_ID",
}
err := db.Create(&outerStructObject).Error
only one of the BeforeCreate() hooks gets called. Other BeforeCreate gets skipped.
Gorm version is jinzhu/gorm v1.9.16
Is there a way which makes a call to both hooks when a create statement is called?
Expecting BeforeCreate hooks to be called for both inner structs - InnerStructA and InnerStructB.
答案1
得分: 1
Peter的评论是准确的,我将在这里分享我的测试和评论,但是使用官方仓库go-gorm/gorm和最新版本v1.25.0
,该版本具有非常相似的结果和一些API的更改。
在创建Outer registry时,可以像这样设置内部对象:
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
}
要触发内部对象的钩子,只需直接创建它们:
innerA := InnerStructA{
A: "123",
}
errCreateInner := db.Create(&innerA).Error
这是一个完整的独立示例:
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"`
}
英文:
Peter's comment is accurate, I'll share my tests and comments here but using the official repo at go-gorm/gorm and latest version v1.25.0
which has very similar results and some changes in the API.
When creating the Outer registry, inner objects 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 inner objects hooks, only by creating them directly:
innerA := InnerStructA{
A: "123",
}
errCreateInner := db.Create(&innerA).Error
Here 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"`
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论