如何使用GORM实现关联字段名称不同且无外键的多表JOIN查询
GORM实现关联字段名不同的多表JOIN查询方案
1. 先定义对应表的模型结构体
首先需要匹配四张表的结构定义GORM模型,示例如下:
// Ticket 对应tickets表 type Ticket struct { TicketID uint `gorm:"primaryKey;column:ticket_id"` CreateUser uint `gorm:"column:create_user"` // 关联users表的user_id字段 // 其他tickets表字段按需补充 } // TicketDetail 对应ticket_details表 type TicketDetail struct { TicketDetailID uint `gorm:"primaryKey;column:ticket_detail_id"` TicketID uint `gorm:"column:ticket_id"` // 其他ticket_details表字段按需补充 } // User 对应users表 type User struct { UserID uint `gorm:"primaryKey;column:user_id"` EmployeeID uint `gorm:"column:employee_id"` // 其他users表字段按需补充 } // Employee 对应employees表 type Employee struct { EmployeeID uint `gorm:"primaryKey;column:employee_id"` // 其他employees表字段按需补充 }
2. 方案一:手写JOIN条件(适配无外键场景,最灵活)
这种方式完全对齐你给出的原生SQL逻辑,不需要提前配置模型关联,哪怕数据库没有实际外键也可以直接使用:
// 定义接收结果的结构体,也可以根据需求用嵌套结构 type TicketFullInfo struct { Ticket TicketDetail User Employee } var result TicketFullInfo err := db.Model(&Ticket{}). Select("tickets.*, ticket_details.*, users.*, employees.*"). Joins("JOIN ticket_details ON tickets.ticket_id = ticket_details.ticket_id"). Joins("JOIN users ON tickets.create_user = users.user_id"). Joins("JOIN employees ON users.employee_id = employees.employee_id"). Where("tickets.ticket_id = ?", 1). // 按需添加筛选条件 Scan(&result).Error
注意:如果多张表存在同名字段,不要直接查
*,需要手动指定别名避免字段覆盖,比如Select("tickets.id as ticket_id, users.name as user_name")
3. 方案二:配置关联后自动生成JOIN条件
如果需要频繁做这类关联查询,可以通过foreignKey和references标签手动指定关联关系,GORM不需要依赖数据库实际外键即可自动生成关联逻辑:
首先给模型补充关联字段:
type Ticket struct { TicketID uint `gorm:"primaryKey;column:ticket_id"` CreateUser uint `gorm:"column:create_user"` // 指定关联规则:当前表的CreateUser字段关联User表的UserID字段 User User `gorm:"foreignKey:CreateUser;references:UserID"` TicketDetail TicketDetail `gorm:"foreignKey:TicketID;references:TicketID"` } type User struct { UserID uint `gorm:"primaryKey;column:user_id"` EmployeeID uint `gorm:"column:employee_id"` // 指定User关联Employee的规则 Employee Employee `gorm:"foreignKey:EmployeeID;references:EmployeeID"` }
配置完成后直接调用Joins预加载即可,GORM会自动拼接关联条件:
var result Ticket err := db.Model(&Ticket{}). Joins("TicketDetail"). Joins("User"). Joins("User.Employee"). Where("tickets.ticket_id = ?", 1). First(&result).Error
内容的提问来源于stack exchange,提问作者Tezza Fazar
相关产品推荐
相关产品推荐

