MySQL - GORM ForeignKey возвращает пустой объект - PullRequest
1 голос
/ 12 февраля 2020

Я почти наверняка делаю это задом наперед. Существует много путаницы вокруг этой функции, по-видимому, вокруг паутины.

Я просто пытаюсь создать связь с внешним ключом, в которой модель Book имеет один Author. Использование MySQL 8.

Когда я запрашиваю книгу, я хочу, чтобы объект автора был возвращен вместе с ней, поэтому возможно, что мой запрос также неверен ... Вот где я нахожусь.

моделей. go

package main

import (
    "github.com/jinzhu/gorm"
    uuid "github.com/satori/go.uuid"
    "time"
)

/*        Base Models
============================= */

type Base struct {
    ID        uuid.UUID  `gorm:"primary_key" json:"id"`
    CreatedAt *time.Time `json:"created_at"`
    UpdatedAt *time.Time `gorm:"index" json:"updated_at"`
    DeletedAt *time.Time `gorm:"index" json:"deleted_at"`
}

type BaseBook struct {
    ISBN        int64     `gorm:"primary_key;auto_increment:false;" json:"isbn"`
    Description string    `gorm:"type:longtext" json:"description"`
    Author      Author    `gorm:"foreignkey:AuthorId" json:"author"`
    AuthorId    uuid.UUID `json:"author_id"`
    Title       string    `json:"title"`
}

// BeforeCreate -  Sets a UUID instead of incremental numeric ID.
func (base *Base) BeforeCreate(scope *gorm.Scope) error {
    id := uuid.NewV4()
    return scope.SetColumn("ID", id)
}

/*          Tables
============================= */

type Book struct {
    Base
    BaseBook
    Events []Event `gorm:"foreignkey:ISBN"`
}

type Event struct {
    BaseBook
}

type Author struct {
    Base
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
    Middle    string `json:"middle"`
}

Есть ли проблема с тем, как я создаю записи здесь в функции seed?

обработчики. go

// GetSeedDatabase - Start seeding database with test data.
func GetSeedDatabase(w http.ResponseWriter, r *http.Request) {
    authors := getSeedDataAuthors()
    books := getSeedDataBooks()
    for _, author := range authors {
        for _, book := range books {
            if book.Author == author.ID.String() {
                newAuthor := Author{
                    Base: Base{
                        ID: author.ID,
                    },
                    FirstName: author.FirstName,
                    LastName:  author.LastName,
                    Middle:    author.Middle,
                }
                newBook := Book{
                    Base: Base{
                        ID: uuid.NewV4(),
                    },
                    BaseBook: BaseBook{
                        AuthorId:    newAuthor.ID,
                        ISBN:        book.ISBN,
                        Title:       book.Title,
                        Description: book.Description,
                    },
                }

                MySQL.Create(newAuthor)
                MySQL.Create(newBook)
            }
        }
    }

    var allAuthors []Author
    MySQL.Find(&allAuthors)

    var allBooks []Book
    MySQL.Find(&allBooks)

    if len(allAuthors) > 0 && len(allBooks) > 0 {
        w.Write([]byte("successfully seeded database"))
        return
    }

    w.Write([]byte("something went wrong seeding database"))
}

// GetAllBooks - Get all books in database.
func GetAllBooks(w http.ResponseWriter, r *http.Request) {
    var allBooks []Book
    MySQL.Find(&allBooks).Related(Author{})
    json.NewEncoder(w).Encode(allBooks)
}

Когда я попадаю в конечную точку книги GetAllBooks, ответ выглядит так:

[
  {
    "id": "0c266efa-3c3c-4bb8-abe6-dbb9b8000cd8",
    "created_at": null,
    "updated_at": null,
    "deleted_at": null,
    "isbn": 9781593275846,
    "description": "JavaScript lies at the heart of almost every modern web application, from social apps to the newest browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex language that you can use to build full-scale applications.",
    "author": {
      "id": "00000000-0000-0000-0000-000000000000",
      "created_at": null,
      "updated_at": null,
      "deleted_at": null,
      "first_name": "",
      "last_name": "",
      "middle": ""
    },
    "author_id": "ba0d07bf-1a12-4742-989b-cdaa4c05ad72",
    "title": "Eloquent JavaScript, Second Edition",
    "Events": null
  },
  {
    "id": "0ea3e0fc-f917-46ea-b55b-d97e916bacd9",
    "created_at": null,
    "updated_at": null,
    "deleted_at": null,
    "isbn": 9781491904244,
    "description": "No matter how much experience you have with JavaScript, odds are you don’t fully understand the language. As part of the \"You Don’t Know JS\" series, this compact guide focuses on new features available in ECMAScript 6 (ES6), the latest version of the standard upon which JavaScript is built.",
    "author": {
      "id": "00000000-0000-0000-0000-000000000000",
      "created_at": null,
      "updated_at": null,
      "deleted_at": null,
      "first_name": "",
      "last_name": "",
      "middle": ""
    },
    "author_id": "c7f6e1b8-9e42-4666-bba8-dd9b229a362e",
    "title": "You Don't Know JS",
    "Events": null
  }
]

Как видите, Author возвращенные объекты являются их пустыми версиями.

Я все еще пробую различные комбинации примеров внешних ключей, которые я нашел в других местах, но все еще не повезло.

Обновление

Итак, первая проблема заключается в том, что GORM просто не добавляет внешние ключи, если вы пытаетесь добавить их с помощью аннотаций на моделях (как у меня). Может быть, это вещь MySQL8? Я не уверен, но я добавил отношение вручную так:

// addConstraints - Since GORM annotations are still broken for foreign keys we do it manually here.
func addConstraints(db *gorm.DB) *gorm.DB {
    log.Println("adding db table constraints")
    db.Model(Book{}).AddForeignKey(
        "author_id",
        "authors(id)",
        "SET DEFAULT",
        "SET DEFAULT",
    )

    return db
}

Теперь я могу предварительно загрузить данные об авторе, которые будут возвращены с книгами, например:

// GetAllBooks - Get all books in database.
func GetAllBooks(w http.ResponseWriter, r *http.Request) {
    var allBooks []Book
    MySQL.Preload("Author").Find(&allBooks)
    json.NewEncoder(w).Encode(allBooks)
}

Ответы [ 2 ]

0 голосов
/ 12 февраля 2020

Обратитесь к этому ответу: { ссылка }

Вам необходимо использовать функцию Горма Preload.

Например:

gormDB.Preload("Author").Find(&allBooks)

Официальный документ: Предварительная загрузка Горм

0 голосов
/ 12 февраля 2020

попробуйте использовать preload http://gorm.io/docs/preload.html

Я приведу пример из моего кода

type Client struct { ID strfmt.UUID4 gorm: "primary_key; тип : uuid; по умолчанию: uuid_generate_v4 () " ApplicationId string gorm:" тип: varchar (40); не ноль " Phone stringjson:" телефон " Email stringjson:" электронная почта " Beneficiaries []Beneficiary gorm: "foreignkey: client_id" json: "получатели" Address string gorm: "null" json: "address" } type Beneficiary struct { ID strfmt.UUID4 gorm: "primary_key; тип: uuid; по умолчанию: uuid_generate_v4 ()" FullName string ClientId strfmt.UUID4 gorm: "type: uuid ССЫЛКИ app_rsv_client (id)" } func (dbm DbManager) GetClientByAppId(appId string) (*model.Client, error) { var client model.Client err := dbm.DB.Preload("Beneficiaries").Where("application_id = ?", appId).Find(&client).Error return &client, err }

...