指定 'gorm: "unique" ',导致属于关系的预加载问题



这是我的Post &用户结构模型:

type Post struct {
ID     string `gorm:"primaryKey"`
Title  string `gorm:"unique"`
UserID string
User   User
}

type User struct {
ID   string `gorm:"primaryKey"`
Name string
}
// Code to create a Post with title & user input
func CreatePost(title string, u User) (Post, error) {
b := Post{Title: title, User: u}
dbIns := GetDB()
if err := dbIns.Create(&b).Error; err != nil {
return Post{}, err
}
return b, nil
}
// Code to get a Post, also preload its User field
func GetOnePost() (Post, error) {
var p Post
dbIns := GetDB()
if err := dbIns.Model(&Post{}).Preload("User").First(&p).Error; err != nil {
return Post{}, err
}
return p, nil
}

这是我从GetOnePost()得到的输出,这正是我所期望的,Post。

用户名不为空。
2022/11/27 15:42:48 Post title: John-Doe's Title, UUID: 32158510-6dcc-4c26-bcb8-7d76a88bda72, authorUUID: 73d020d3-eb8d-4bf7-9f57-e821c5deceed 
2022/11/27 15:42:48 User name: John-Doe, UUID: 73d020d3-eb8d-4bf7-9f57-e821c5deceed

但是,当我指定User。名称必须是唯一的(因为我希望每个用户都有不同的名称)
注意:是的,我确实迁移到一个新表。

type User struct {
ID   string `gorm:"primaryKey"`
Name string `gorm:"unique"`
}

GetOnePost()的输出更改为:(请忽略UUID)

2022/11/27 15:57:49 Post title: John-Doe's Title, UUID: 26355816-c376-497a-a250-be118c5933e2, authorUUID: e858cd72-56b9-4884-b6e6-94121c36719b 
2022/11/27 15:57:49 User name: , UUID:

问题是返回的Post。当我向User模型添加唯一约束时,User似乎是空的。

如果我从用户模型中删除唯一约束,它将返回正常(Post。用户非空)。所以在我看来,问题出在"独特"这个词上。部分。

老实说,我无法重现您的问题。无论如何,我添加了我的尝试来重现你的问题,如预期的那样工作。让我先显示代码,然后我将为您提供一个简短的解释:

package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"github.com/google/uuid"
_ "github.com/lib/pq"
)
type Post struct {
ID     string `gorm:"primaryKey"`
Title  string `gorm:"unique"`
UserID string
User   User
}
type User struct {
ID   string `gorm:"primaryKey"`
Name string `gorm:"unique"`
}
// Code to create a Post with title & user input
func CreatePost(db *gorm.DB, title string, u User) (Post, error) {
id := uuid.NewString()
b := Post{ID: id, Title: title, User: u}
if err := db.Create(&b).Error; err != nil {
return Post{}, err
}
return b, nil
}
// Code to get a Post, also preload its User field
func GetOnePost(db *gorm.DB) (Post, error) {
var p Post
if err := db.Model(&Post{}).Preload("User").First(&p).Error; err != nil {
return Post{}, err
}
return p, nil
}
func main() {
dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(&User{})
db.AutoMigrate(&Post{})
defer db.Exec("DROP TABLE users")
defer db.Exec("DROP TABLE posts")
userId := uuid.NewString()
_, err = CreatePost(db, "Learn Go", User{
ID:   userId,
Name: "John Doe",
})
if err != nil {
panic(err)
}
post, err := GetOnePost(db)
if err != nil {
panic(err)
}
// this leads to a Duplicate error SQLSTATE 23505 in DB
// if err := db.Create(&User{
//  ID:   uuid.NewString(),
//  Name: "John Doe",
// }).Error; err != nil {
//  panic(err)
// }
fmt.Printf("post's details: %vn", post)
}

代码或多或少与您提供的相同。我添加了两个延迟函数调用,以便在每次运行代码后删除表。由于这一点,我们总是可以确保使用提供的最新表定义。然后,我在Postgres中检查UNIQUE约束是否存在,并且我正确地找到了它。然而,当我尝试运行我的代码时,我成功地检索了User信息。如果您试图取消以此注释// this leads to a Duplicate error SQLSTATE 23505 in DB开头的代码块的注释,您将得到一个重复的错误,因此在数据库端强制执行约束。

让我知道如果使用我的解决方案你的代码工作太!

相关内容

  • 没有找到相关文章

最新更新