Горм возвращает только один вместо нескольких результатов - PullRequest
0 голосов
/ 08 апреля 2019

Я написал коды удара, и он возвращает только 1 строку вместо 4:

package main

import (
    "fmt"

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

type Post struct {
    gorm.Model
    Title    string
    Text     string
    Comments []Comment
}

type Comment struct {
    gorm.Model
    Text   string
    PostID uint `gorm:"foreignkey:ID;association_foreignkey:PostID"`
}

func main() {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect to database")
    }
    defer db.Close()

    db.DropTableIfExists(&Post{}, &Comment{})
    db.AutoMigrate(&Post{}, &Comment{})

    // fill db
    db.Create(&Post{Title: "test1 title", Text: "text1"})
    db.Create(&Post{Title: "test2 title", Text: "text2"})
    db.Create(&Post{Title: "test3 title", Text: "text3"})
    db.Create(&Comment{Text: "test1 comment1", PostID: 3})
    db.Create(&Comment{Text: "test2 comment1", PostID: 2})
    db.Create(&Comment{Text: "test3 comment2", PostID: 2})
    db.Create(&Comment{Text: "test4 comment3", PostID: 2})
    db.Create(&Comment{Text: "test5 comment4", PostID: 2})
    db.Create(&Comment{Text: "test6 comment1", PostID: 1})
    //end fill db

    var myPost Post
    var comments Comment
    db.First(&myPost, 2)
    db.Model(&myPost).Related(&comments)

    fmt.Println(myPost)
    fmt.Println(comments)
}

, и это мой вывод:

{{2 2019-04-08 17:04:20.3781288 +0430 +0430 2019-04-08 17:04:20.3781288 +0430 +0430 <nil>} test2 title text2 []}
{{5 2019-04-08 17:04:20.4091133 +0430 +0430 2019-04-08 17:04:20.4091133 +0430 +0430 <nil>} test5 comment4 2}

вы можете увидеть только одну строку:

test5 comment4 

и я ожидаю этого результата:

test2 comment1
test3 comment2
test4 comment3
test5 comment4

Что я должен сделать, чтобы получить результат в 4 строки?

Я уже прочитал всю документацию по gorm.и этот пример документа не работает для меня, как я ожидаю http://doc.gorm.io/associations.html#has-many

Has Many
// User has many emails, UserID is the foreign key
type User struct {
    gorm.Model
    Emails   []Email
}

type Email struct {
    gorm.Model
    Email   string
    UserID  uint
}

db.Model(&user).Related(&emails)
//// SELECT * FROM emails WHERE user_id = 111; // 111 is user's primary key

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

В прикрепленном фрагменте немало вопросов, которые будут решать их один за другим:

# 1

type Post struct {
    gorm.Model
    Title    string
    Text     string
    Comments []Comment
}

type Comment struct {
    gorm.Model
    Text   string
    PostID uint `gorm:"foreignkey:ID;association_foreignkey:PostID"`
}

Здесь также присвоения внешнего ключа foreignkey:IDпоскольку внешний ключ ассоциации не нужен и не помещен .

Для Внешний ключ : по умолчанию gorm использует имя типа владельца плюс имя его первичного ключаполе.В вашем случае: PostID.

  • Post - это имя типа владельца
  • ID, равное его первичный ключ .

Вам понадобится использовать тег forignkey, только если вы хотите изменить имя поля в структуре Comment.Например, PostNumber вместо PostID.Поэтому вам нужно добавить тег с foreignkey:PostNumber и изменить PostID в Comment на PostNumber.

Для Association ForeignKey , он используется, если вы хотите сказать gormиспользовать другой член, отличный от первичного ключа владельца.Например, AnotherID в приведенном ниже примере.

Другая проблема заключается в том, что вы должны указывать эти теги в полях has many, а не сам внешний ключ.Полный пример будет выглядеть так:

type Post struct {
    gorm.Model
    AnotherID uint     <-------------------------------------------------------
    Title     string                                                           |
    Text      string                                                           |
    Comments  []Comment `gorm:"foreignkey:PostNumber;association_foreignkey:AnotherID"`
}                                             |
                                              |
type Comment struct {                         |
    gorm.Model                                |
    Text       string                         |
    PostNumber uint    <----------------------
}

Обратите внимание, что эти два типа должны иметь одинаковый тип.


# 2

Можно поспорить об использовании defer db.Close().Из документов ,

Редко закрывать БД, так как дескриптор БД должен быть долгоживущим и совместно использоваться многими программами.

В этом примере нормально defer закрыть базу данных.Хотя это произойдет автоматически, если вы не позвоните.Основная причина, по которой я комментирую это, состоит в том, чтобы сказать вам, что в больших приложениях вам не нужно делать это с каждым соединением.Безопасно просто вызывать sql.Open() для глобальной переменной и использовать ее без необходимости db.Close().

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

db.DB().SetConnMaxLifetime(X) // sets the maximum amount of time a connection may be reused.
db.DB().SetMaxIdleConns(X) // sets the maximum number of connections in the idle connection pool.
db.DB().SetMaxOpenConns(X) // sets the maximum number of open connections to the database.

См. это обсуждение для получения дополнительной информации.


# 3

Приведенные ниже вызовы могут завершиться с ошибкой:

db.DropTableIfExists(&Post{}, &Comment{})

db.AutoMigrate(&Post{}, &Comment{})

db.Create(&Post{Title: "test1 title", Text: "text1"})

Итак, ВСЕГДА проверьте наличие ошибок, вы можете сделать это, проверив Error членаgorm.DB struct:

err = db.DropTableIfExists(&Post{}, &Comment{}).Error
if err != nil {
    // handle error
}

err = db.AutoMigrate(&Post{}, &Comment{}).Error
// Check error

err = db.Create(&Post{Title: "test1 title", Text: "text1"}).Error
// Check error

# 4

Это ответ на ваш вопрос :

Вы не проходитеПередавая срез от Comment до db.Model(&myPost).Related(&comments) и ожидая взамен среза, который не будет работать по понятным причинам, вам нужно изменить:

var comments Comment

на

var comments []Comment
0 голосов
/ 08 апреля 2019

Со вчерашнего дня я размышлял над этой проблемой и только сейчас нашел ее.Я просто забыл определить комментарий var как массив.

"Один вопрос, связанный с вашим вопросом, заключается в том, что вы не передаете фрагмент в gorm и не ожидаете получить его в ответ. Изменить комментарии var Комментарий к комментариям var []Комментарий. Обратите внимание на фрагмент [] " Абдулла сказал

var comments Comment

до

var comments []Comment

благодаря Абдулла

...