首页 > 后端开发 > Golang > 正文

创建新对象后如何返回嵌套实体?

PHPz
发布: 2024-02-10 21:40:15
转载
542 人浏览过

创建新对象后如何返回嵌套实体?

在PHP中,创建新对象后如何返回嵌套实体是一个常见的问题。当我们需要在一个类中创建一个新的对象,并将其作为另一个实体的属性时,我们需要注意一些技巧和方法。首先,我们可以在类的构造函数中创建新的对象,并将其赋值给属性。然后,我们可以使用$this关键字来引用当前对象,并访问其属性。另外,我们也可以使用静态方法或工厂模式来创建新的对象,并将其返回给调用者。无论哪种方法,返回嵌套实体的关键是正确地处理对象之间的关联关系,确保它们在各个实体之间正确地交互和传递数据。通过这些方法,我们可以轻松地在PHP中创建和返回嵌套的实体对象。

问题内容

模型 account 包含嵌套结构 - currencyuser

当我在数据库中创建 account 的新实例,然后在响应中返回它时,嵌套实体为空:

type account struct {
    basemodel
    name       string          `gorm:"size:64;not null" json:"name"`
    balance    decimal.decimal `gorm:"type:decimal(16, 2);default:0;not null;" json:"balance"`
    userid     int             `gorm:"not null" json:"-"`
    user       user            `gorm:"foreignkey:userid" json:"user"`
    currencyid int             `gorm:"not null" json:"-"`
    currency   currency        `gorm:"foreignkey:currencyid" json:"currency"`
}

type createaccountbody struct {
    name       string          `json:"name" binding:"required"`
    balance    decimal.decimal `json:"balance"`
    currencyid int             `json:"currency_id" binding:"required"`
}

func createaccount(ctx *gin.context) {
    body := createaccountbody{}

    if err := ctx.bind(&body); err != nil {
        log.println("error while binding body:", err)
        ctx.json(
            http.statusbadrequest,
            gin.h{"error": "wrong request parameters"},
        )
        return
    }

    account := account {
        name:       body.name,
        balance:    body.balance,
        currencyid: body.currencyid,
        userid:     1,
    }
    
    if result := db.db.create(&account); result.error != nil {
        log.println("unable to create an account:", result.error)
    }    

    ctx.json(http.statuscreated, gin.h{"data": account})
}


登录后复制

为了避免此问题,我使用单独的查询刷新帐户变量:

db.DB.Create(&account)
db.DB.Preload("User").Preload("Currency").Find(&account, account.ID)
ctx.JSON(http.StatusCreated, gin.H{"data": account})
登录后复制

这是达到预期结果的最有效、最正确的方法吗?

解决方法

我将与您分享我通常是如何处理这种情况的。首先,让我分享一下代码。

main.go 文件

package main

import (
    "context"

    "gogindemo/handlers"

    "github.com/gin-gonic/gin"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

var (
    db  *gorm.db
    ctx *gin.context
)

func init() {
    dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable"
    var err error
    db, err = gorm.open(postgres.open(dsn), &gorm.config{})
    if err != nil {
        panic(err)
    }

    db.automigrate(&handlers.currency{})
    db.automigrate(&handlers.user{})
    db.automigrate(&handlers.account{})
}

func adddb() gin.handlerfunc {
    return func(ctx *gin.context) {
        ctx.request = ctx.request.withcontext(context.withvalue(ctx.request.context(), "db", db))
        ctx.next()
    }
}

func main() {
    db.create(&handlers.user{id: 1, name: "john doe"})
    db.create(&handlers.user{id: 2, name: "mary hut"})
    db.create(&handlers.currency{id: 1, name: "eur"})
    db.create(&handlers.currency{id: 2, name: "usd"})

    r := gin.default()
    r.post("/account", adddb(), handlers.createaccount)

    r.run()
}
登录后复制

在这里,我刚刚添加了用于引导数据库对象的代码并向其中添加了一些虚拟数据。

handlers/handlers.go 文件

package handlers

import (
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/shopspring/decimal"
    "gorm.io/gorm"
)

type User struct {
    Id   int
    Name string
}

type Currency struct {
    Id   int
    Name string
}

type Account struct {
    Id         int
    Name       string          `gorm:"size:64;not null" json:"name"`
    Balance    decimal.Decimal `gorm:"type:decimal(16, 2);default:0;not null;" json:"balance"`
    UserID     int             `gorm:"not null" json:"-"`
    User       User            `gorm:"foreignKey:UserID" json:"user"`
    CurrencyID int             `gorm:"not null" json:"-"`
    Currency   Currency        `gorm:"foreignKey:CurrencyID" json:"currency"`
}

type CreateAccountBody struct {
    Name       string          `json:"name" binding:"required"`
    Balance    decimal.Decimal `json:"balance"`
    CurrencyID int             `json:"currency_id" binding:"required"`
}

func CreateAccount(c *gin.Context) {
    db, ok := c.Request.Context().Value("DB").(*gorm.DB)
    if !ok {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
        return
    }
    var accountReq CreateAccountBody
    if err := c.BindJSON(&accountReq); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "wrong request body payload"})
        return
    }

    // create Account & update the "account" variable
    account := Account{Name: accountReq.Name, Balance: accountReq.Balance, CurrencyID: accountReq.CurrencyID, UserID: 1}
    db.Create(&account).Preload("Currency").Preload("User").Find(&account, account.Id)

    c.IndentedJSON(http.StatusCreated, account)
}
登录后复制

在此文件中,我实际上通过在 context 中传递的 db 与数据库进行通信。现在,回到你的问题。
如果 currency//account 和 user/currency//account 和 user/account 之间的关系是 1:1 类型,那么,您应该依赖 preload 子句。这将在单独的查询中加载相关实体,而不是将其添加到 inner join 之间的关系是 1:1 类型,那么,您应该依赖 preload 子句。这将在单独的查询中加载相关实体,而不是将其添加到 inner join 子句中。

请告诉我这是否解决了您的问题,谢谢!

以上是创建新对象后如何返回嵌套实体?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:stackoverflow.com
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!