我正在使用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(对OS和版本)的两个外键,我希望能够通过其关键操作系统查询GlobalDefault表,并获取已经包含完整AgentMetadata的数据结构 .

经过很长一段时间阅读大量文档,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 . 但是,它不是正确的元数据 .

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

enter image description here

enter image description here

当我调用 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在DB中创建外键(我注意到创建的模式没有从GlobalDefault到AgentMetadata的外键)?