gorm 使用join的时候,怎么自动填充到struct中?

1. 运行环境

go版本: 1.17
gorm版本:1.21 (也就是2.0)

2. 问题描述?

使用join关联查询的时候,如果多个表中有相同名称的字段,就无法正确的给struct 填充数据。
以下是其中一部分的struct, 实际的表可能有十几个字段

type Model struct {
   Id         int64 `gorm:"primaryKey;autoIncrement" json:"id" form:"id"`
  CreatedAt  time.Time `gorm:"not null;" json:"-"`
  UpdatedAt  time.Time `gorm:"not null" json:"-"`
  DeletedAt  gorm.DeletedAt `gorm:"index" json:"-"`
  CreateTime int64 `gorm:"autoCreateTime:milli" json:"createTime" ` // 创建时间
  UpdateTime int64 `gorm:"autoUpdateTime:milli" json:"updateTime" ` // 更新时间
}
type Article struct {
    Model
    Title  string `gorm:"not null: " json:"type" form:"type"`
    UserId int64  `gorm:"not null;" json:"userId" form:"userId"`
    User   *User  `gorm:"foreignKey:UserId" json:"user"` // 为了正确填充数据,使用了外键
    NodeId int64  `gorm:"not null;" json:"nodeId" form:"nodeId"`
    Node   *Node  `gorm:"foreignKey:NodeId" json:"node"`
}

type User struct {
    Model
    Username sql.NullString `gorm:"size:32;unique;" json:"username"`
    Phone    string         `gorm:"size:30;" json:"phone"`
}

type Node struct {
    Model
    Name string `gorm:"size:32;unique;" json:"name"`
}

// 保存查询结果
type ArticleViewResult struct {
   *Article
   User *User `gorm:"embedded" json:"user"`
   Node *Node `gorm:"embedded" json:"node"`
}

方案一: 使用join查询

使用join查询的时候,由于存在相同的字段名称,导致填充的struct的数据不正确,代码大概如果如下
例如:db.Table("article").Joins("left join user on article.user_id = user.id").Joins("left join node on article.id = node.id").Select("article.*, user.*, node.*").Scan(&[]ArticleViewResult) ,后面还有一些条件,查询发现 article的Id 填充了node.id, 猜测可能是由于 字段一样,导致填充错误。

方案二:使用外键

阅读文档发现可以使用外键,关联模式下使用join就可以正确填充数据,但是,使用 AutoMigrate 的 时候,发现表被创建了外键,但是不让使用外键又无法使用关联关系。

目前方式:
自动创建表之后,然后在手动删除外键,暂时可以解决这个问题。

不知大家有什么好的方式去解决么,或者说自动创建表的时候,禁止创建外键,目前没有从文档中找到相关的配置,能关闭外键的创建,
求助了,感谢🙏!

在论坛找到了一个同样的问题:问答:gorm 不设置外键可以关联查询吗 ?

3. 您实际得到的结果?

  1. 如果不使用外键,怎么方便切正确的去填充到struct中
  2. 或者是自动Migrate的时候,不创建数据库外键,外键逻辑仅仅是程序上的
附言 1  ·  2年前

可能没表述清楚, 麻烦之处:在于有多个字段(20-30个左右)的时候,select写起来很麻烦,

讨论数量: 3

首先定义好需要返回的ArticleViewResult结构体

type ArticleViewResult struct {
     Title        string     `json:"title"`
     Phone    string         `json:"phone"`
     Name     string         `json:"name"`
}

其次在查询的时候,Select字段跟定义的结构体字段一一对应

var result []ArticleViewResult 
db.Table("article").Joins("left join user on article.user_id = user.id").Joins("left join node on article.id = node.id").Select("article.title, user.phone, node.name").Scan(&result)

最后,留给你自己看结果,谢谢

2年前 评论
little-bird (楼主) 2年前
type AutoGenerated struct {
    Article Article `json:"article"`
    User User `json:"user"`
    Node Node `json:"node"`
}
type Article struct {
    ID int `json:"id"`
    Title string `json:"title"`
}
type User struct {
    ID int `json:"id"`
    Phone string `json:"phone"`
}
type Node struct {
    ID int `json:"id"`
    Name string `json:"name"`
}

是这样吗?

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!