Gorm returns 只有一个而不是多个结果
Gorm returns just one instead of multiple results
我写了打击代码,它 returns 只有 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
从昨天开始就在想这个问题,现在才发现问题所在。我只是忘了将 var comment 定义为数组。
"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表示
var comments Comment
到
var comments []Comment
感谢Abdullah
附件中有不少问题,将一一解决:
#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
的赋值和关联外键的赋值都是不必要的和错位的。
对于Foreign Key:默认情况下,gorm 使用所有者的类型名称加上其主键字段的名称。在你的情况下:PostID
.
Post
是所有者的类型名称
ID
是它的主键.
如果要更改 Comment
结构中的字段名称,则只需使用 forignkey
标记。例如,PostNumber
而不是 PostID
。因此,您需要使用 foreignkey:PostNumber
添加标签并将 Comment
中的 PostID 更改为 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()
的用法争论不休。来自 docs、
It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines.
本例中,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.
有关详细信息,请参阅 this 讨论。
#3
下面的调用可以失败:
db.DropTableIfExists(&Post{}, &Comment{})
db.AutoMigrate(&Post{}, &Comment{})
db.Create(&Post{Title: "test1 title", Text: "text1"})
所以,总是 检查错误,你可以通过检查 gorm.DB
结构的 Error
成员来做到这一点:
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)
并期望 return 中的一个切片由于显而易见的原因而无法工作,因此您需要更改:
var comments Comment
到
var comments []Comment
我写了打击代码,它 returns 只有 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
从昨天开始就在想这个问题,现在才发现问题所在。我只是忘了将 var comment 定义为数组。
"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表示
var comments Comment
到
var comments []Comment
感谢Abdullah
附件中有不少问题,将一一解决:
#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
的赋值和关联外键的赋值都是不必要的和错位的。
对于Foreign Key:默认情况下,gorm 使用所有者的类型名称加上其主键字段的名称。在你的情况下:PostID
.
Post
是所有者的类型名称ID
是它的主键.
如果要更改 Comment
结构中的字段名称,则只需使用 forignkey
标记。例如,PostNumber
而不是 PostID
。因此,您需要使用 foreignkey:PostNumber
添加标签并将 Comment
中的 PostID 更改为 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()
的用法争论不休。来自 docs、
It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines.
本例中,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.
有关详细信息,请参阅 this 讨论。
#3
下面的调用可以失败:
db.DropTableIfExists(&Post{}, &Comment{})
db.AutoMigrate(&Post{}, &Comment{})
db.Create(&Post{Title: "test1 title", Text: "text1"})
所以,总是 检查错误,你可以通过检查 gorm.DB
结构的 Error
成员来做到这一点:
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)
并期望 return 中的一个切片由于显而易见的原因而无法工作,因此您需要更改:
var comments Comment
到
var comments []Comment