当前位置: 首页 > news >正文

Gorm(八)预加载方式

在 Gorm 中,PreloadJoins 用于处理关联查询,解决“N+1 查询问题”并高效加载关联数据。二者适用场景不同,且支持灵活的自定义逻辑。以下是详细说明:

一、Preload:预加载关联数据(单次查询关联表)

Preload 会在主查询之后,单独执行一条 SQL 查询关联表,将关联数据一次性加载到主模型中,避免循环查询(N+1 问题)。适用于所有关联关系(一对一、一对多、多对多)。

1. 基础用法(单次预加载)

加载主模型时,同时加载指定的关联字段。

示例(一对多:查询用户时预加载订单)

type User struct {gorm.ModelName   stringOrders []Order // 一对多关联
}type Order struct {gorm.ModelProduct stringUserID  uint
}// 预加载用户的 Orders 关联
var users []User
db.Preload("Orders").Find(&users) 
// 执行两条 SQL:
// 1. SELECT * FROM users;(查询主表)
// 2. SELECT * FROM orders WHERE user_id IN (1,2,3...);(查询关联表,IN 条件包含主表所有 ID)

结果users 切片中每个 UserOrders 字段已填充对应的订单数据。

2. Preload 带条件(Preload(db.Where...)

预加载时可通过 db.Where 过滤关联数据,只加载符合条件的关联记录。

示例(只预加载金额大于 100 的订单)

var users []User
// 预加载用户的 Orders,且订单金额 > 100
db.Preload("Orders", "amount > ?", 100).Find(&users)
// 关联查询 SQL:SELECT * FROM orders WHERE user_id IN (...) AND amount > 100;

复杂条件:支持多个条件组合(使用 db.Where 链式调用):

db.Preload("Orders", func(tx *gorm.DB) *gorm.DB {return tx.Where("amount > 100").Where("status = ?", "paid")
}).Find(&users)
// 关联查询条件:amount > 100 AND status = 'paid'
3. 自定义 Preload(嵌套预加载、多级关联)

Preload 支持嵌套预加载(关联的关联),或通过自定义函数实现复杂逻辑。

示例 1:嵌套预加载(用户 → 订单 → 订单项)

type Order struct {gorm.ModelProduct  stringUserID   uintItems    []OrderItem // 订单包含多个订单项(一对多)
}type OrderItem struct {gorm.ModelOrderID uintName    string
}// 预加载用户的订单,同时预加载订单的订单项
db.Preload("Orders.Items").Find(&users)
// 执行 3 条 SQL:users → orders → order_items

示例 2:自定义预加载函数(排序、分页)

// 预加载用户的订单,并按创建时间倒序,只取前 5 条
db.Preload("Orders", func(tx *gorm.DB) *gorm.DB {return tx.Order("created_at DESC").Limit(5)
}).Find(&users)

二、Joins:关联查询(单次 SQL 联表查询)

Joins 通过 SQL 联表查询(LEFT JOIN / INNER JOIN) 将主表和关联表合并为一条 SQL,适用于一对一需要过滤主表数据的场景(一对多联表会导致主表记录重复)。

1. 基础用法(单次联表查询)

示例(一对一:查询用户时联表查询身份证信息)

type User struct {gorm.ModelName   stringIDCard IDCard // 一对一关联
}type IDCard struct {gorm.ModelNumber stringUserID uint
}// 联表查询用户和身份证(LEFT JOIN)
var users []User
db.Joins("IDCard").Find(&users)
// SQL:SELECT users.*, id_cards.* FROM users LEFT JOIN id_cards ON users.id = id_cards.user_id;

结果User.IDCard 字段会填充关联的身份证数据。

2. Joins 带条件(过滤主表或关联表)

联表时可通过 Where 同时过滤主表和关联表的数据。

示例(查询有身份证且年龄 > 18 的用户)

db.Joins("IDCard").Where("users.age > ? AND id_cards.number IS NOT NULL", 18).Find(&users)
// SQL:LEFT JOIN 后通过 WHERE 过滤主表(users.age)和关联表(id_cards.number)
3. JoinsSelect 结合(指定返回字段)

联表查询时可通过 Select 只返回需要的字段,避免字段冲突(如主表和关联表都有 created_at 时)。

db.Joins("IDCard").Select("users.id, users.name, id_cards.number").Find(&users)
// 只返回用户的 id、name 和身份证的 number 字段

三、PreloadJoins 的对比与适用场景

特性PreloadJoins
底层实现执行多条 SQL(主表 + 关联表)执行单条联表 SQL(JOIN)
适用关联类型一对一、一对多、多对多(均适用)优先一对一(一对多会导致主表记录重复)
主表记录是否重复不重复(关联数据放在切片/对象中)一对多场景会重复(主表记录随关联数复制)
能否过滤主表数据不能(仅过滤关联数据)能(通过联表条件过滤主表)
性能多表查询但避免重复数据,适合大量关联单条 SQL 但可能返回重复数据,适合简单关联

四、最佳实践

  1. 一对多/多对多关联:优先用 Preload,避免 Joins 导致的主表记录重复。
    例如:查询用户及其所有订单,Preload("Orders")Joins("Orders") 更清晰(后者会让一个用户对应多条重复记录)。

  2. 一对一关联PreloadJoins 均可,Joins 性能略优(单条 SQL)。
    例如:查询用户及其身份证,Joins("IDCard") 更高效。

  3. 需要通过关联表过滤主表:必须用 Joins
    例如:查询“有未支付订单的用户”,需通过 Joins("Orders").Where("orders.status = 'unpaid'") 过滤。

  4. 复杂关联逻辑:用 Preload 自定义函数,支持排序、分页、嵌套预加载。

总结

  • Preload:通过多条 SQL 预加载关联数据,适合所有关联类型,避免主表重复,支持嵌套和条件过滤。
  • Joins:通过单条联表 SQL 查询,适合一对一或需过滤主表的场景,注意一对多的记录重复问题。

根据关联类型和查询需求选择合适的方法,可兼顾性能和代码清晰度。

http://www.dtcms.com/a/532045.html

相关文章:

  • 网站开发与设计的实训场地WordPress无法自动推送
  • 【找指针数组最大值】2022-11-24
  • 自己做网站能赚钱吗做spa的网站怎么推广
  • 网络管理中的名词
  • gitlab配置git的ssh秘钥
  • 机器狗进化论:当“园区跑腿”遇上具身智能,一场静悄悄的变革正在发生
  • 江宁区建设工程质量监督站网站学校网站源码开源
  • Docker LXC深度解析:从基础概念到实战演练
  • Spring Boot3零基础教程,docker 批量安装软禁,笔记68
  • 【C语言】函数栈帧的创建和销毁
  • 架构的尺度:从单机到分布式,服务端技术的深度演进
  • 优秀国内个人网站网址网站设计需要那些模块
  • 【ARM驱动】【FreeROTS移植到ARM驱动平台介绍】
  • BELLE中的表1
  • go-ethereum core之交易索引txIndexer
  • 描述对于营销型网站建设很重要飘红效果更佳信阳做网站 汉狮网络
  • 油猴脚本学习1——元数据头部
  • mysql 如何让事件执行
  • PantherX2 debain/armbian Jellyfin10.10.7升级10.11启动后无法监听端口8096的解决办法
  • 网站建设利弊中山币做网站公司
  • Kaleidoscope for mac 文件对比工具
  • LeetCode 1901.寻找峰值2
  • 沈阳建设网站费用北京网站优化软件
  • 【Android】【底层原理】深入解析SELinux模块
  • 阮一峰《TypeScript 教程》学习笔记——注释指令
  • 最好的开发网站建设价格app免费制作平台下载
  • 供应链进销存源码uniapp全开源ERP多仓库管理系统pc+app手机端
  • 生物化学Learning Track(15)酶活性的调节
  • 站酷设计网站官网入口下载国外手机设计网站
  • Rust 泛型与特性