【问题标题】:Foreign keys and related data with gorm带有gorm的外键和相关数据
【发布时间】:2017-12-20 12:51:21
【问题描述】:

我正在使用 golang 和 gorm 与 MySQL 数据库通信。

我有一张带有发布元数据的表格:

type OSType string
const (
    Windows OSType = "windows"
    Mac     OSType = "mac"
)

type AgentMetadata struct {
    Version         string              `gorm:"primary_key"`
    OS              OSType              `gorm:"primary_key" sql:"type:ENUM('windows','mac')"`
    Name            string              `sql:"not null"`
    Description     string              `sql:"not null"`
    ReleaseNotesUrl string              `sql:"not null"`

    UpdateTime      time.Time           `sql:"DEFAULT:current_timestamp"`
}

版本由复合键标识 - 操作系统和版本(编号)。

我有另一个表,它定义了客户端应该下载的默认版本(按操作系统):

type GlobalDefault struct {
    OS              OSType          `gorm:"primary_key" sql:"type:ENUM('windows','mac')"`
    Version         string
    AgentMetadata   AgentMetadata   

    UpdateTime      time.Time       `sql:"DEFAULT:current_timestamp"`
}

我想要定义从 GlobalDefault 到 AgentMetadata 的两个外键(操作系统和版本对),我希望能够通过其关键操作系统查询 GlobalDefault 表并取回已经包含完整的数据结构代理元数据。

经过很长时间并阅读了大量文档、SO 问题和代码示例后,我尝试执行以下操作:

func (repository *AgentRepository)GetGlobalDefault(os OSType) (error, AgentMetadata) {
    gd := GlobalDefault{ OS:os }

    result := AgentMetadata{}
    return repository.connection.Find(&gd).Related(&result, "OS", "Version").Error, result
}

从某种意义上说,这“有效”了,它确实使结果充满了 AgentMetadata。但是,它不是正确的元数据。

在我的测试中,我添加了两条元数据记录和一条默认记录:

当我调用 err, queryResult := ar.GetGlobalDefault(defaultAgent.OS) 而不是获取 1.2.3 版本的元数据时,我得到了 1.2.3.1 的元数据。

确实,当我打开 gorm 日志时,我看到它运行了查询:

[2017-07-15 17:51:50] [276.74ms] SELECT * FROM global_defaults WHERE global_defaults.os = 'windows'

[2017-07-15 17:51:50] [276.55ms] SELECT * FROM agent_metadata WHERE (os = 'windows')

首先,它忽略了我在 agent_metadata 表中有一个复合键这一事实,其次,它没有使用连接执行单个查询,而是执行了两个查询(这确实是浪费时间)。

另一件困扰我的事情是我必须明确指定外键名称,而根据文档,似乎不需要指定它们,或者至少可以通过添加标签来实现:

type GlobalDefault struct {
    OS              OSType          `gorm:"primary_key" sql:"type:ENUM('windows','mac')"`
    Version         string
    AgentMetadata   AgentMetadata   `gorm:"ForeignKey:OS;AssociationForeignKey:OS"`

    UpdateTime      time.Time       `sql:"DEFAULT:current_timestamp"`
}

这里我只为 OS 列添加了一个标签,但是,我尝试连接外键名称,这两个选项似乎都没有对结果产生影响。如果没有在 API 中明确指定外键名称,相关数据将不会被读取。将名称传递给查询意味着我的数据库映射没有合并在一个地方,我不喜欢这样。

我的情况可以解决吗?我可以有一个复合外键吗?我可以在一个地方指定所有 ORM 属性吗?如何让 gorm 在数据库中创建外键(我注意到架构是在没有从 GlobalDefault 到 AgentMetadata 的外键的情况下创建的)?

【问题讨论】:

    标签: mysql go orm go-gorm


    【解决方案1】:

    如何让 gorm 在数据库中创建外键?

    这是一个示例:

    db.AutoMigrate(&model.User{}).
            AddForeignKey("account_id", "accounts(id)", "CASCADE", "CASCADE").
            AddForeignKey("role_id", "roles(id)", "RESTRICT", "RESTRICT")
    

    【讨论】:

      猜你喜欢
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 2020-04-24
      • 1970-01-01
      • 2017-01-10
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      相关资源
      最近更新 更多