亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Golang Gorm 一對多和一對一

Golang Gorm 一對多和一對一

Go
SMILET 2021-12-20 15:17:46
我正在嘗試通過構建一個小原型訂單管理應用程序來學習 Go 和 Gorm。數據庫是 MySQL。通過簡單的查詢,Gorm 表現出色。然而,當試圖獲得一個涉及一對多組合和一對一關系的結果集時,Gorm 似乎達不到要求。毫無疑問,實際上是我缺乏了解。我似乎無法找到任何關于我想要完成的工作的在線示例。任何幫助將不勝感激。去結構// Ordertype Order struct {    gorm.Model    Status  string    OrderItems   []OrderItem}// Order line itemtype OrderItem struct {    gorm.Model    OrderID uint    ItemID  uint    Item    Item    Quantity int}// Producttype Item struct {    gorm.Model    ItemName     string    Amount       float32}數據庫表ordersid | status 1 | pendingorder_itemsid | order_id | item_id | quantity 1 | 1        | 1       | 1 2 | 1        | 2       | 4itemsid | item_name   | amount 1 | Go Mug      | 12.49 2 | Go Keychain | 6.95 3 | Go T-Shirt  | 17.99當前查詢order := &Order if err := db.Where("id = ? and status = ?", reqOrder.id, "pending").First(&order).Error; err != nil {    fmt.Printf(err.Error())}db.Model(&order).Association("OrderItems").Find(&order.OrderItems)結果(gorm 進行 2 db 查詢)order == Order {  id: 1,  status: pending,  OrderItems[]: {    {      ID: 1,      OrderID: 1,      ItemID: 1,      Item: nil,      Quantity: 1,    },    {      ID: 2,      OrderID: 1,      ItemID: 2,      Item: nil,      Quantity: 4,    } }替代查詢order := &Orderdb.Where("id = ? and status = ?", reqOrder.id, "cart").Preload("OrderItems").Preload("OrderItems.Item").First(&order)結果(gorm 進行 3 db 查詢)order == Order {  id: 1,  status: pending,  OrderItems[]: {    {      ID: 1,      OrderID: 1,      ItemID: 1,      Item: {        ID: 1,        ItemName: Go Mug,        Amount: 12.49,      }      Quantity: 1,    },    {      ID: 2,      OrderID: 1,      ItemID: 2,      Item: {        ID: 2,        ItemName: Go Keychain,        Amount: 6.95,      },      Quantity: 4,    } }理想的結果上面的“替代查詢”產生了理想的查詢結果。但是,Gorm 進行了 3 個單獨的數據庫查詢來實現此目的。理想情況下,使用 1 個(或 2 個)數據庫查詢可以獲得相同的結果。這可以通過幾個連接在 MySQL 中完成。Gorm 允許連接。但是,我希望利用 Gorm 的一些關系魔法。謝謝一堆!
查看完整描述

2 回答

?
慕容708150

TA貢獻1831條經驗 獲得超4個贊

如本期所述,gorm 并非旨在使用連接來預加載其他結構值。如果您想繼續使用 gorm 并且有能力使用連接加載值,則必須使用gorm 中公開的SQL Builder,并編寫一些代碼來掃描所需的值。


如果必須考慮許多表,這將變得繁重。如果xorm可用作選項,則它們支持加載結構值。在查找項目符號下描述,這里。


注意:我沒有掃描所有字段,只是足以理解這一點。


示例:


package main


import (

    "log"


    "github.com/jinzhu/gorm"

    _ "github.com/jinzhu/gorm/dialects/sqlite"

    "github.com/kylelemons/godebug/pretty"

)


// Order

type Order struct {

    gorm.Model

    Status     string

    OrderItems []OrderItem

}


// Order line item

type OrderItem struct {

    gorm.Model

    OrderID  uint

    ItemID   uint

    Item     Item

    Quantity int

}


// Product

type Item struct {

    gorm.Model

    ItemName string

    Amount   float32

}


var (

    items = []Item{

        {ItemName: "Go Mug", Amount: 12.49},

        {ItemName: "Go Keychain", Amount: 6.95},

        {ItemName: "Go Tshirt", Amount: 17.99},

    }

)


func main() {

    db, err := gorm.Open("sqlite3", "/tmp/gorm.db")

    db.LogMode(true)

    if err != nil {

        log.Panic(err)

    }

    defer db.Close()


    // Migrate the schema

    db.AutoMigrate(&OrderItem{}, &Order{}, &Item{})


    // Create Items

    for index := range items {

        db.Create(&items[index])

    }

    order := Order{Status: "pending"}

    db.Create(&order)

    item1 := OrderItem{OrderID: order.ID, ItemID: items[0].ID, Quantity: 1}

    item2 := OrderItem{OrderID: order.ID, ItemID: items[1].ID, Quantity: 4}

    db.Create(&item1)

    db.Create(&item2)


    // Query with joins

    rows, err := db.Table("orders").Where("orders.id = ? and status = ?", order.ID, "pending").

        Joins("Join order_items on order_items.order_id = orders.id").

        Joins("Join items on items.id = order_items.id").

        Select("orders.id, orders.status, order_items.order_id, order_items.item_id, order_items.quantity" +

            ", items.item_name, items.amount").Rows()

    if err != nil {

        log.Panic(err)

    }


    defer rows.Close()

    // Values to load into

    newOrder := &Order{}

    newOrder.OrderItems = make([]OrderItem, 0)


    for rows.Next() {

        orderItem := OrderItem{}

        item := Item{}

        err = rows.Scan(&newOrder.ID, &newOrder.Status, &orderItem.OrderID, &orderItem.ItemID, &orderItem.Quantity, &item.ItemName, &item.Amount)

        if err != nil {

            log.Panic(err)

        }

        orderItem.Item = item

        newOrder.OrderItems = append(newOrder.OrderItems, orderItem)

    }

    log.Print(pretty.Sprint(newOrder))

}

輸出:


/tmp/main.go.go:55) 

[2018-06-18 18:33:59]  [0.74ms]  INSERT INTO "items" ("created_at","updated_at","deleted_at","item_name","amount") VALUES ('2018-06-18 18:33:59','2018-06-18 18:33:59',NULL,'Go Mug','12.49')  

[1 rows affected or returned ] 


(/tmp/main.go.go:55) 

[2018-06-18 18:33:59]  [0.50ms]  INSERT INTO "items" ("created_at","updated_at","deleted_at","item_name","amount") VALUES ('2018-06-18 18:33:59','2018-06-18 18:33:59',NULL,'Go Keychain','6.95')  

[1 rows affected or returned ] 


(/tmp/main.go.go:55) 

[2018-06-18 18:33:59]  [0.65ms]  INSERT INTO "items" ("created_at","updated_at","deleted_at","item_name","amount") VALUES ('2018-06-18 18:33:59','2018-06-18 18:33:59',NULL,'Go Tshirt','17.99')  

[1 rows affected or returned ] 


(/tmp/main.go.go:58) 

[2018-06-18 18:33:59]  [0.71ms]  INSERT INTO "orders" ("created_at","updated_at","deleted_at","status") VALUES ('2018-06-18 18:33:59','2018-06-18 18:33:59',NULL,'pending')  

[1 rows affected or returned ] 


(/tmp/main.go.go:61) 

[2018-06-18 18:33:59]  [0.62ms]  INSERT INTO "order_items" ("created_at","updated_at","deleted_at","order_id","item_id","quantity") VALUES ('2018-06-18 18:33:59','2018-06-18 18:33:59',NULL,'49','145','1')  

[1 rows affected or returned ] 


(/tmp/main.go.go:62) 

[2018-06-18 18:33:59]  [0.45ms]  INSERT INTO "order_items" ("created_at","updated_at","deleted_at","order_id","item_id","quantity") VALUES ('2018-06-18 18:33:59','2018-06-18 18:33:59',NULL,'49','146','4')  

[1 rows affected or returned ] 


(/tmp/main.go.go:69) 

[2018-06-18 18:33:59]  [0.23ms]  SELECT orders.id, orders.status, order_items.order_id, order_items.item_id, order_items.quantity, items.item_name, items.amount FROM "orders" Join order_items on order_items.order_id = orders.id Join items on items.id = order_items.id WHERE (orders.id = '49' and status = 'pending')  

[0 rows affected or returned ] 

--- ONLY ONE QUERY WAS USED TO FILL THE STRUCT BELOW

2018/06/18 18:33:59 {Model:      {ID:        49,

              CreatedAt: 0001-01-01 00:00:00 +0000 UTC,

              UpdatedAt: 0001-01-01 00:00:00 +0000 UTC,

              DeletedAt: nil},

 Status:     "pending",

 OrderItems: [{Model:    {ID:        0,

                          CreatedAt: 0001-01-01 00:00:00 +0000 UTC,

                          UpdatedAt: 0001-01-01 00:00:00 +0000 UTC,

                          DeletedAt: nil},

               OrderID:  49,

               ItemID:   145,

               Item:     {Model:    {ID:        0,

                                     CreatedAt: 0001-01-01 00:00:00 +0000 UTC,

                                     UpdatedAt: 0001-01-01 00:00:00 +0000 UTC,

                                     DeletedAt: nil},

                          ItemName: "Go Mug",

                          Amount:   12.489999771118164},

               Quantity: 1},

              {Model:    {ID:        0,

                          CreatedAt: 0001-01-01 00:00:00 +0000 UTC,

                          UpdatedAt: 0001-01-01 00:00:00 +0000 UTC,

                          DeletedAt: nil},

               OrderID:  49,

               ItemID:   146,

               Item:     {Model:    {ID:        0,

                                     CreatedAt: 0001-01-01 00:00:00 +0000 UTC,

                                     UpdatedAt: 0001-01-01 00:00:00 +0000 UTC,

                                     DeletedAt: nil},

                          ItemName: "Go Keychain",

                          Amount:   6.949999809265137},

               Quantity: 4}]}


查看完整回答
反對 回復 2021-12-20
?
泛舟湖上清波郎朗

TA貢獻1818條經驗 獲得超3個贊

從上面的答案中,要獲取訂單列表,它將是:


 .....


    orders := make([]Order, 0)


    for rows.Next() {

        order := Order{}

        orderItem := OrderItem{}


        item := Item{}

        err = rows.Scan(&order.ID, &order.Status, &orderItem.OrderID, &orderItem.ItemID, &orderItem.Quantity, &item.ItemName, &item.Amount)

        if err != nil {

            log.Panic(err)

        }


        orderItem.Item = item


        order.OrderItems = append(order.OrderItems, orderItem)


        orders = append(orders, order)

    }


    log.Print(pretty.Sprint(orders))

}


查看完整回答
反對 回復 2021-12-20
  • 2 回答
  • 0 關注
  • 343 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號