GORM表关联一对一

143 阅读6分钟

gorm文档gorm.io/zh_CN/docs/…

Belongs Togorm.io/zh_CN/docs/…

一个表关联一个表

mysql表

CREATE TABLE `qcc_room` (
  `room_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
  `is_deleted` bigint unsigned DEFAULT '0',
  `room_name` varchar(191) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '房间名',
  `room_type` tinyint NOT NULL DEFAULT '0' COMMENT '房间类型 1进线房 2机房',
  `qcc_important_device_room_id` bigint NOT NULL COMMENT '房间id',
  `qcc_room_room_id` bigint unsigned DEFAULT NULL COMMENT '主键ID',
  PRIMARY KEY (`room_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='房间表';
​
CREATE TABLE `qcc_important_device` (
  `important_device_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
  `is_deleted` bigint unsigned DEFAULT '0' COMMENT '是否删除',
  `device_name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '设备名',
  `room_id` bigint NOT NULL COMMENT '房间id',
  `room_name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '房间名',
  `room_type` tinyint NOT NULL DEFAULT '0' COMMENT '房间类型 1进线房 2机房',
  PRIMARY KEY (`important_device_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='重要设备表';

结构体

package room
​
import (
    "gorm.io/plugin/soft_delete"
    "xkginweb/global"
)
​
type QccRoom struct {
    RoomId    uint                  `json:"room_id" gorm:"primarykey;comment:主键ID"` // 主键ID
    CreatedAt global.LocalTime      `gorm:"type:datetime(0);autoCreateTime;comment:创建时间" json:"createdAt"`
    UpdatedAt global.LocalTime      `gorm:"type:datetime(0);autoUpdateTime;comment:更新时间" json:"updatedAt"`
    IsDeleted soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt;default:0" json:"isDeleted" structs:"is_deleted"`
    RoomName  string                `json:"room_name" gorm:"not null;default:'';comment:房间名"`
    RoomType  int8                  `json:"room_type" gorm:"not null;default:0;comment:房间类型 1进线房 2机房"`
}
​
func (QccRoom) TableName() string {
    return "qcc_room"
}
​
package importantDevice
​
import (
    "gorm.io/plugin/soft_delete"
    "xkginweb/global"
)
​
// 重要设备表
​
type QccImportantDevice struct {
    ImportantDeviceId uint                  `gorm:"primarykey;comment:主键ID" json:"important_device_id"`
    CreatedAt         global.LocalTime      `gorm:"type:datetime;comment:创建时间" json:"created_at"`
    UpdatedAt         global.LocalTime      `gorm:"type:datetime;comment:更新时间" json:"updated_at"`
    IsDeleted         soft_delete.DeletedAt `gorm:"type:bigint(20) unsigned;default:0;comment:是否删除" json:"is_deleted"`
    DeviceName        string                `gorm:"type:varchar(50);default:'';comment:设备名;NOT NULL" json:"device_name"`
    RoomId            uint                  `gorm:"type:bigint(20);comment:房间id;NOT NULL" json:"room_id"`
    //references的作用是 使用 QccRoom.room_id 作为引用
    QccRoom *QccRoom `gorm:"foreignKey:RoomId;references:room_id;" json:"room"` 
}
​
func (QccImportantDevice) TableName() string {
    return "qcc_important_device"
}
​
type QccRoom struct {
    RoomId   uint   `json:"room_id"` // 主键ID
    RoomName string `json:"room_name"`
    RoomType int8   `json:"room_type"`
}

然后去在gorm中在声明模型

核心代码:绑定外键

 // 使用 RoomId 作为外键 关联到qcc_room表的room_id上
QccRoom *QccRoom `gorm:"foreignKey:RoomId;references:room_id;" json:"room"`
​
type QccRoom struct {
    RoomId   uint   `json:"room_id" gorm:"primarykey;comment:主键ID"` // 主键ID
    RoomName string `json:"room_name" gorm:"not null;default:'';comment:房间名"`
    RoomType int8   `json:"room_type" gorm:"not null;default:0;comment:房间类型 1进线房 2机房"`
}

使用方法

根据id查询设备

func (service *ImportantDeviceService) GetImportantDevice(id uint) (importantDevice *importantDevice.QccImportantDevice, err error) {
    err = global.KSD_DB.Where("qcc_important_device.important_device_id = ?", id).Preload("QccRoom", func(db *gorm.DB) *gorm.DB {
        return db.Table("qcc_room").Select("room_id,room_name,room_type")
    }).First(&importantDevice).Error
    return
}

代码分析

  1. global.KSD_DB.Where("qcc_important_device.important_device_id = ?", id):这部分是查询条件,用于过滤 qcc_important_device 表中 important_device_id 字段等于给定 id 的记录。
  2. Preload("QccRoom", func(db *gorm.DB) *gorm.DB { ... }):这是预加载操作,用于加载关联的房间信息。在这里,使用了匿名函数来定制加载的行为。
  3. db.Table("qcc_room"):这是使用 GORM 的 Table 方法,用于指定关联表的名称为 "qcc_room",而不是默认情况下的结构体名(例如,"QccRoom")。
  4. Select("room_id,room_name,room_type"):这是使用 GORM 的 Select 方法,用于选择关联表中的特定字段,即 "room_id"、"room_name" 和 "room_type"。这样可以避免加载关联表的所有字段,只选择需要的字段,以减少数据传输量和提高性能。
  5. First(&importantDevice):最后,通过 First 方法执行查询,并将结果存储在 importantDevice 变量中。这里假设 importantDevice 是与 qcc_important_device 表对应的结构体。

注意 Joins 和 Preload 的区别

使用Joins 预加载操作的sql语句如下

SELECT
    `qcc_important_device`.`important_device_id`,
    `qcc_important_device`.`created_at`,
    `qcc_important_device`.`updated_at`,
    `qcc_important_device`.`is_deleted`,
    `qcc_important_device`.`device_name`,
    `qcc_important_device`.`room_id`,
    `QccRoom`.`room_id` AS `QccRoom__room_id`,
    `QccRoom`.`created_at` AS `QccRoom__created_at`,
    `QccRoom`.`updated_at` AS `QccRoom__updated_at`,
    `QccRoom`.`is_deleted` AS `QccRoom__is_deleted`,
    `QccRoom`.`room_name` AS `QccRoom__room_name`,
    `QccRoom`.`room_type` AS `QccRoom__room_type` 
FROM
    `qcc_important_device`
    LEFT JOIN `qcc_room` `QccRoom` ON `qcc_important_device`.`important_device_id` = `QccRoom`.`room_id` 
    AND `QccRoom`.`is_deleted` = 0 
WHERE
    qcc_important_device.important_device_id = 1 
    AND `qcc_important_device`.`is_deleted` = 0 
ORDER BY
    `qcc_important_device`.`important_device_id` 
    LIMIT 1

使用Preload 预加载操作的sql语句如下

SELECT
    room_id,
    room_name,
    room_type 
FROM
    `qcc_room` 
WHERE
    `qcc_room`.`room_id` = 1
    
​
SELECT
    * 
FROM
    `qcc_important_device` 
WHERE
    qcc_important_device.important_device_id = 2 
    AND `qcc_important_device`.`is_deleted` = 0 
ORDER BY
    `qcc_important_device`.`important_device_id` 
    LIMIT 1

一个表关联两个表

mysql表

CREATE TABLE `qcc_cooling_pool_device` (
  `cooling_pool_device_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
  `is_deleted` bigint unsigned DEFAULT '0' COMMENT '是否删除',
  `cooling_pool_id` bigint NOT NULL COMMENT '冷池id',
  `room_id` bigint NOT NULL COMMENT '房间id',
  `device_name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '设备名',
  PRIMARY KEY (`cooling_pool_device_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='冷池检测项表';
​
CREATE TABLE `qcc_room` (
  `room_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
  `is_deleted` bigint unsigned DEFAULT '0',
  `room_name` varchar(191) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '房间名',
  `room_type` tinyint NOT NULL DEFAULT '0' COMMENT '房间类型 1进线房 2机房',
  `qcc_important_device_room_id` bigint NOT NULL COMMENT '房间id',
  `qcc_room_room_id` bigint unsigned DEFAULT NULL COMMENT '主键ID',
  PRIMARY KEY (`room_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='房间表';
​
CREATE TABLE `qcc_cooling_pool` (
  `cooling_pool_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
  `is_deleted` bigint unsigned DEFAULT '0',
  `cooling_pool_name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '冷池名',
  `room_id` bigint NOT NULL COMMENT '房间id',
  PRIMARY KEY (`cooling_pool_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='冷池表';

qcc_cooling_pool_device.room_id 关联 qcc_room.room_id

qcc_cooling_pool_device.cooling_pool_id关联 qcc_cooling_pool.cooling_pool_id

结构体

此处只展示qcc_cooling_pool_device表的,其他可以用转换工具自行转换

package coolingPoolDevice
​
import (
    "gorm.io/plugin/soft_delete"
    "xkginweb/global"
)
​
// 冷池检测项表
​
type QccCoolingPoolDevice struct {
    CoolingPoolDeviceId uint                  `gorm:"primary_key;AUTO_INCREMENT;comment:主键ID" json:"cooling_pool_device_id"`
    CreatedAt           global.LocalTime      `gorm:"type:datetime;comment:创建时间" json:"created_at"`
    UpdatedAt           global.LocalTime      `gorm:"type:datetime;comment:更新时间" json:"updated_at"`
    IsDeleted           soft_delete.DeletedAt `gorm:"type:bigint(20) unsigned;default:0;comment:是否删除" json:"is_deleted"`
    DeviceName          string                `gorm:"type:varchar(50);default:'';comment:设备名;NOT NULL" json:"device_name"`
    CoolingPoolId       uint                  `gorm:"type:bigint(20);comment:冷池id;NOT NULL" json:"cooling_pool_id"`
    RoomId         uint            `gorm:"type:bigint(20);comment:房间id;NOT NULL" json:"room_id"`
    QccCoolingPool *QccCoolingPool `gorm:"foreignKey:CoolingPoolId;references:cooling_pool_id;" json:"cooling_pool"`
    QccRoom *QccRoom `gorm:"foreignKey:RoomId;references:room_id;" json:"room"`
}
​
​
func (QccCoolingPoolDevice) TableName() string {
    return "qcc_cooling_pool_device"
}
​
type QccCoolingPool struct {
    CoolingPoolId   uint   `json:"cooling_pool_id"` // 主键ID
    CoolingPoolName string `json:"cooling_pool_name"`
}
​
type QccRoom struct {
    RoomId   uint   `json:"room_id"` // 主键ID
    RoomName string `json:"room_name"`
    RoomType int8   `json:"room_type"`
}

使用方法

根据id查询冷池检测项表

func (service *CoolingPoolDeviceService) GetCoolingPoolDevice(id uint) (coolingPoolDevice *coolingPoolDevice.QccCoolingPoolDevice, err error) {
    err = global.KSD_DB.Where("cooling_pool_device_id = ?", id).Preload("QccRoom", func(db *gorm.DB) *gorm.DB {
        return db.Table("qcc_room").Select("room_id,room_name,room_type")
    }).Preload("QccCoolingPool", func(db *gorm.DB) *gorm.DB {
        return db.Table("qcc_cooling_pool").Select("cooling_pool_id,cooling_pool_name")
    }).First(&coolingPoolDevice).Error
    return
}

gorm输入sql

SELECT
    cooling_pool_id,
    cooling_pool_name 
FROM
    `qcc_cooling_pool` 
WHERE
    `qcc_cooling_pool`.`cooling_pool_id` = 1
----------------------------------------------------------  
SELECT
    room_id,
    room_name,
    room_type 
FROM
    `qcc_room` 
WHERE
    `qcc_room`.`room_id` = 1
----------------------------------------------------------      
SELECT
    * 
FROM
    `qcc_cooling_pool_device` 
WHERE
    cooling_pool_device_id = 1 
    AND `qcc_cooling_pool_device`.`is_deleted` = 0 
ORDER BY
    `qcc_cooling_pool_device`.`cooling_pool_device_id` 
    LIMIT 1