简体   繁体   English

Gorm仅返回一个而不是多个结果

[英]Gorm returns just one instead of multiple results

I wrote blow codes and it returns just 1 row instead of 4: 我写了打击代码,它只返回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)
}

and this is my output: 这是我的输出:

{{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}

you can see just one row: 您只能看到一行:

test5 comment4 

and I expect this result: 我期望这个结果:

test2 comment1
test3 comment2
test4 comment3
test5 comment4

What should I do to get 4 rows result? 我应该怎么做才能得到4行结果?

I already read all the documentation of gorm. 我已经阅读了gorm的所有文档。 and this example of doc is not working for me as I expect http://doc.gorm.io/associations.html#has-many 并且此文档示例对我不起作用,因为我期望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

There quite a few issues in the attached snippet, will tackle them one by one: 附件中有很多问题,将一一解决:

#1 #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"`
}

Here, the assignments of the foreign key foreignkey:ID as well as the association foreign key are both unnecessary and misplaced . 在此,外键foreignkey:ID以及关联外键的分配都是不必要的并且放错了位置

For the Foreign Key : By default, gorm uses the owner's type name plus the name of its primary key field. 对于外键 :默认情况下,gorm使用所有者的类型名称加上其主键字段的名称。 In your case: PostID . 在您的情况下: PostID

  • Post is the the owner's type name Post所有者的类型名称
  • ID is its primary key . ID其主键

You would only need to use the forignkey tag if you want to change the name of the feild in the Comment struct. 如果要在Comment结构中更改领域的名称,则仅需要使用forignkey标记。 For example, PostNumber instead of PostID . 例如,用PostNumber代替PostID So you would need to add a tag with foreignkey:PostNumber and change the PostID in Comment to PostNumber . 因此,您需要添加一个带有foreignkey:PostNumber的标记, foreignkey:PostNumber Comment中的PostNumber更改为PostNumber

For the Association ForeignKey , It's used if you want to tell gorm to use a different member other than the owner's primary key. 对于Association ForeignKey ,如果要告诉gorm使用所有者的主键以外的其他成员,则使用它。 For example, AnotherID in the below example. 例如,以下示例中的AnotherID

Another problem would be that you should specify these tags on the has many fields and not the foreign key itself. 另一个问题是,您应该在has many字段而不是外键本身上指定这些标签。 A complete example would look like this: 一个完整的示例如下所示:

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    <----------------------
}

Note that these two have to have the same type. 请注意,这两个必须具有相同的类型。


#2 #2

One can argue about the usage of defer db.Close() . 可以争论一下defer db.Close()的用法。 From the docs , 文档中

It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines. 关闭数据库很少,因为数据库句柄是长期存在的并且在许多goroutine之间共享。

In this example, it's fine to defer the closing of the database. 在此示例中,可以defer数据库的关闭。 Though, it will happen automatically if you don't call it. 不过,如果您不调用它,它将自动发生。 The main reason why I am commenting about it is to tell you that in big applications, you don't need to do that with each connection. 我对此进行评论的主要原因是告诉您,在大型应用程序中,您不需要为每个连接都这样做。 It's safe to just call sql.Open() on a global variable and use it without the need to db.Close() . 仅在全局变量上调用sql.Open()并使用它而无需db.Close()

In this case, you also don't want it to open as many connections as it pleases so you might want to fine tune the following parameters: 在这种情况下,您也不希望它打开尽可能多的连接,因此您可能需要微调以下参数:

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.

See this discussion for more information. 有关更多信息,请参见此讨论。


#3 #3

The below calls can fail: 以下调用可能会失败:

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

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

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

So, ALWAYS check for errors, you can do that with checking the Error member of the gorm.DB struct: 因此, 始终检查错误,可以通过检查gorm.DB结构的Error成员来gorm.DB

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 #4

This is the answer to your question : 这是您的问题的答案

You are passing not passing a slice of Comment to db.Model(&myPost).Related(&comments) and expecting a slice in return which will not work for obvious reasons, so you would need to change: 您没有传递未将Comment片段传递给db.Model(&myPost).Related(&comments)并且期望返回的片段由于明显的原因而无法正常工作,因此您需要进行以下更改:

var comments Comment

to

var comments []Comment

I was thinking on this problem since yesterday and I found the problem just now. 从昨天开始,我一直在思考这个问题,而现在才发现问题。 I just forgot to define var comment as an array. 我只是忘了将var注释定义为数组。

"The one related to your question is that you are not passing a slice to gorm and expecting a slice in return. change var comments Comment to var comments []Comment. Notice the slice []" Abdullah said “与您的问题有关的一个问题是,您没有将切片传递给gorm并期望获得切片作为回报。将var注释注释更改为var注释[]注释。注意切片[]” 阿卜杜拉

var comments Comment

to

var comments []Comment

thanks to Abdullah 感谢阿卜杜拉

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM