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

Golang GORM系列:GORM 高级查询教程

有效的数据检索是任何程序功能的基础。健壮的Go对象关系映射包(称为GORM)除了标准的CRUD操作之外,还提供了复杂的查询功能。这是学习如何使用GORM进行高级查询的综合资源。我们将涵盖WHERE条件、连接、关联、预加载相关数据,甚至涉及原始SQL查询。到最后,你的Go应用程序将具备以无与伦比的精度提取和操作数据的能力。

在这里插入图片描述

GORM where 条件

使用WHERE条件优化查询对于提取特定的数据子集至关重要。

步骤1:基本的WHERE子句

使用GORM的‘ Where ’方法来应用条件:

var expensiveProducts []Product
db.Where("price > ?", 50).Find(&expensiveProducts)

步骤2:AND & OR条件

使用逻辑运算符组合多个条件:

var filteredProducts []Product
db.Where("price > ? AND category = ?", 50, "Electronics").Find(&filteredProducts)

GORM中的连接和关联

模型之间的关联支持跨多个表的复杂查询。

步骤1:定义关联

在你的模型结构中建立关联:

type User struct {gorm.ModelOrders []Order
}type Order struct {gorm.ModelUserID  uintProduct string
}

步骤2:执行连接

使用GORM的‘ Joins ’方法从关联的模型中检索数据:

var usersWithOrders []User
db.Joins("JOIN orders ON users.id = orders.user_id").Find(&usersWithOrders)

GORM预加载相关数据

有效地加载相关数据以最小化数据库查询。

步骤1:预加载关联

使用GORM的‘ Preload ’方法来快速加载相关数据:

var users []User
db.Preload("Orders").Find(&users)

步骤2:嵌套预加载

预加载嵌套关联,用于全面的数据检索;

var users []User
db.Preload("Orders.OrderItems").Find(&users)

GORM中的原始SQL查询

对于复杂的查询,GORM允许执行原始SQL语句。

步骤1:原始SQL查询

使用GORM的‘ raw ’方法执行原始SQL查询:

var products []Product
db.Raw("SELECT * FROM products WHERE price > ?", 50).Scan(&products)

步骤2:绑定变量

使用绑定变量进行更安全、更高效的查询:

var categoryName = "Electronics"
var expensivePrice = 100
var filteredProducts []Product
db.Raw("SELECT * FROM products WHERE category = ? AND price > ?", categoryName, expensivePrice).Scan(&filteredProducts)

完整示例

在现实场景中,用户有多个订单,一个订单可能包含多个产品。为了实现这一点,我们需要引入一个中间表(即关联表)来表示订单和产品之间的多对多关系。

数据模型如下

  1. User 模型:表示用户。
  2. Order 模型:表示订单。
  3. Product 模型:表示产品。
  4. OrderProduct 模型:表示订单和产品之间的多对多关系(中间表)。

完整代码

我们通过引入中间表 order_products,实现了订单和产品之间的多对多关系。使用 Preload 方法可以高效地加载嵌套关系,避免多次查询数据库。这个实例展示了如何在 GORM 中处理复杂的多对多关系,并支持一个订单包含多个产品的场景。你可以根据实际需求进一步扩展模型和查询逻辑,例如添加更多的字段或条件。

package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)// User 模型
type User struct {ID    uintName  stringEmail stringOrders []Order // 一个用户有多个订单
}// Order 模型
type Order struct {ID      uintUserID  uintUser    User // 订单属于一个用户Products []Product `gorm:"many2many:order_products;"` // 一个订单有多个产品
}// Product 模型
type Product struct {ID    uintName  stringPrice float64Orders []Order `gorm:"many2many:order_products;"` // 一个产品可以属于多个订单
}// OrderProduct 模型(中间表)
type OrderProduct struct {OrderID   uintProductID uintQuantity  int // 订单中某个产品的数量
}func main() {// 连接数据库dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {panic("failed to connect database")}// 自动迁移模型db.AutoMigrate(&User{}, &Order{}, &Product{}, &OrderProduct{})// 插入测试数据user := User{Name: "John Doe", Email: "john@example.com"}db.Create(&user)product1 := Product{Name: "Laptop", Price: 1200.00}product2 := Product{Name: "Mouse", Price: 25.00}db.Create(&product1)db.Create(&product2)order := Order{UserID: user.ID}db.Create(&order)// 添加产品到订单db.Model(&order).Association("Products").Append([]Product{product1, product2})// 查询用户及其订单和产品信息var users []Userdb.Preload("Orders.Products").Find(&users)// 打印结果for _, user := range users {fmt.Printf("User: %s, Email: %s\n", user.Name, user.Email)for _, order := range user.Orders {fmt.Printf("  Order ID: %d\n", order.ID)for _, product := range order.Products {fmt.Printf("    Product: %s, Price: %.2f\n", product.Name, product.Price)}}}
}
数据模型
  • Order 和 Product 的多对多关系
    • 一个订单可以包含多个产品,一个产品也可以属于多个订单。
    • 使用 gorm:"many2many:order_products;" 标签定义多对多关系,order_products 是中间表的名称。
  • 中间表 OrderProduct
    • 中间表包含 OrderIDProductID 作为外键,以及额外的字段 Quantity 表示订单中某个产品的数量。
查询数据
  • 使用 Preload 方法预加载嵌套关系:
    • Preload("Orders") 加载用户的订单。
    • Preload("Orders.Products") 加载每个订单的产品。
  • 这样可以避免 N+1 查询问题,提高查询效率。
中间表数据
// 添加产品到订单
db.Model(&order).Association("Products").Append([]Product{product1, product2})
  1. Association("Products")
    • 这里使用了 GORM 的 Association 方法,表示操作 Order 模型与 Product 模型之间的多对多关系。
    • ProductsOrder 模型中定义的关联字段。
  2. Append([]Product{product1, product2})
    • Append 方法用于将产品添加到订单中。
    • 这里传入了两个产品:product1product2
  3. 中间表数据的插入
    • 当调用 Append 方法时,GORM 会自动在中间表 order_products 中插入数据。
    • 插入的数据包括:
      • OrderID:当前订单的 ID。
      • ProductID:每个产品的 ID。
      • Quantity:如果中间表有其他字段(如 Quantity),可以通过额外配置插入数据(见下文)。

假设:

  • 订单的 ID 是 1
  • 产品的 ID 分别是 1(Laptop)和 2(Mouse)。

调用 Append 方法后,GORM 会自动在 order_products 表中插入以下数据:

OrderIDProductIDQuantity
110
120

注意:如果中间表有其他字段(如 Quantity),需要额外处理。


如果需要插入 Quantity 字段

如果中间表 OrderProduct 包含 Quantity 字段,并且希望在插入时设置数量,可以通过以下方式实现:

修改后的代码
// 添加产品到订单,并设置数量
orderProduct1 := OrderProduct{OrderID: order.ID, ProductID: product1.ID, Quantity: 1}
orderProduct2 := OrderProduct{OrderID: order.ID, ProductID: product2.ID, Quantity: 2}
db.Create(&orderProduct1)
db.Create(&orderProduct2)
  • 手动创建 OrderProduct 记录,并设置 OrderIDProductIDQuantity
  • 使用 db.Create 将记录插入到 order_products 表中。

最后总结

从Go应用程序获取和修改数据的最全面的工具集是由GORM复杂的查询功能提供的。通过学习如何使用连接和关系、预加载相关数据,甚至尝试原始SQL查询,可以很快掌握精确而复杂地数据查询。这些特性不仅提高了程序的效率,而且还提供了对以前难以想象的复杂数据情况的访问。

相关文章:

Golang GORM系列:GORM 高级查询教程

有效的数据检索是任何程序功能的基础。健壮的Go对象关系映射包(称为GORM)除了标准的CRUD操作之外,还提供了复杂的查询功能。这是学习如何使用GORM进行高级查询的综合资源。我们将涵盖WHERE条件、连接、关联、预加载相关数据,甚至涉…...

智能GUI Agent是什么,有什么应用领域

智能GUI Agent是什么 研究背景与目的:GUI长期主导人机交互,LLM特别是多模态模型的出现,为GUI自动化带来变革,催生了基于LLM的GUI智能体。这些智能体可理解自然语言指令,处理复杂GUI元素并执行操作,改变了用户与软件交互方式。论文旨在梳理该领域发展脉络,剖析关键要素,…...

k8s优雅操作pod容器组

k8s优雅操作pod容器组 回退备份 kubectl get deploy deployName -o yaml>>deployName-bak-date "%Y-%m-%d".yaml获取副本数 replicasecho | kubectl get -o template deploy/deployName --template{{.spec.replicas}}停止容器组 kubectl scale deployment …...

在 Mac ARM 架构上使用 nvm 安装 Node.js 版本 16.20.2

文章目录 1. 安装 nvm(如果还没有安装的话)2. 加载 nvm 配置3. 列出特定系列的 Node.js 版本(远程):4. 安装 Node.js 16.20.25. 使用指定版本的 Node.js6. 验证安装 在 Mac ARM 架构上使用 nvm 安装 Node.js 版本 16.…...

MySQL创建存储过程和存储函数

【图书推荐】《MySQL 9从入门到性能优化(视频教学版)》-CSDN博客 《MySQL 9从入门到性能优化(视频教学版)(数据库技术丛书)》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…...

PyQt学习记录03——批量设置水印

0. 目录 PyQt学习记录01——加法计算器 PyQt学习记录02——串口助手 1. 前言 本次主要是为了学习Qt中的 QFileDialog 函数, QFileDialog.getExistingDirectory:用于选择文件夹,返回的是一个文件夹路径。 QFileDialog.getOpenFileName&…...

vivo手机和Windows电脑连接同一个WiFi即可投屏!

虽然现在很多人喜欢刷手机,但是对于长时间需要使用手机办公的人来说,手机屏幕还是太小了,当人一天二十四小时中要花费近十个小时摆弄手机,就会渴望手机屏幕能够大一点,至少看的时候,眼睛舒服一点。 因为嫌弃…...

芯盾时代数据安全产品体系,筑牢数据安全防线

芯盾时代数据安全治理(DSG)框架,以国家法律法规、行业监管标准、行业最佳实践为依据,从数据安全战略出发,以数据分类分级为支撑,构数据安全管理体系、数据安全技术体系、数据安全运营体系与数据安全监督评价…...

异位妊娠唯一相关的是年龄(U型曲线)

异位妊娠唯一相关的是年龄(U型曲线) 简介 异位妊娠,俗称宫外孕,是指受精卵在子宫体腔以外着床发育的异常妊娠过程 。正常情况下,受精卵会在子宫内着床并发育成胎儿,但在异位妊娠中,受精卵却在…...

CTF-WEB: 利用Web消息造成DOM XSS

如果索引中有类似如下代码 <!-- Ads to be inserted here --> <div idads> </div> <script>window.addEventListener(message, function(e) {document.getElementById(ads).innerHTML e.data;}); </script>这行代码的作用是将接收到的消息内容…...

【通俗易懂说模型】一篇弄懂几个经典CNN图像模型(AlexNet、VGGNet、ResNet)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …...

Unity世界坐标转成UI坐标

Unity世界坐标转成UI坐标 介绍转换代码合并方法总结 介绍 在Unity中官方提供了很多坐标转换的API&#xff0c;但是还没有一个API是将世界坐标系转换成UI的坐标系&#xff0c;世界坐标系在屏幕中的位置是不固定的所以有时候需要转换成UI坐标系**&#xff08;注意这里不是转换成…...

自制游戏——斗罗大陆

很简陋&#xff0c;没有图&#xff0c;请见谅 // mine[0] 级数 // mine[1] 战力 //mine[2] 1 白虎 //mine[2] 2 昊天锤 //mine[2] 3 蓝银草 #include <bits/stdc.h> using namespace std; int mine[100],live3, dou 1, luo 1, da 1, bag[1000], huan 0, lia…...

MindStudio制作MindSpore TBE算子(四)算子测试(ST测试-Ascend910B/ModelArts)--失败尝试

上一节&#xff0c;MindStudio制作MindSpore TBE算子&#xff08;三&#xff09;算子测试&#xff08;ST测试&#xff09;&#xff0c;因此缺乏对应的硬件环境导致无法进行ST测试&#xff0c;导致难以自安&#xff0c;今天搞来Ascend910B服务器来填坑&#xff0c;看看是否是硬件…...

二、交换机的vlan子设备接入

一、交换机的vlan设置-CSDN博客 二、交换机的vlan子设备接入-CSDN博客 接上篇的文章&#xff0c;本文接入了子设备 网络结构如下&#xff1a; 用路由器A和POE交换机B代替第一篇中的笔记本电脑&#xff0c;路由器A和交换机B都关闭DHCP服务&#xff0c;并分别接入一个IPC&#…...

EFCore相关知识分享

EFCore相关知识分享 文章目录 EFCore相关知识分享前言EFCore 的优势SaveChang的作用EF Core 查询优化小技巧使用投影&#xff08;投影到所需的数据类型&#xff09;延迟加载&#xff08;Lazy Loading&#xff09;与显式加载&#xff08;Eager Loading&#xff09;使用 AsNoTrac…...

检测网络安全漏洞 工具 网络安全 漏洞扫描 实验

实验一的名称为信息收集和漏洞扫描 实验环境&#xff1a;VMware下的kali linux2021和Windows7 32&#xff0c;网络设置均为NAT&#xff0c;这样子两台机器就在一个网络下。攻击的机器为kali,被攻击的机器为Windows 7。 理论知识记录&#xff1a; 1.信息收集的步骤 2.ping命令…...

deepseek + kimi 高效生成PPT

1.在deepseek中生成ppt大纲 2.将大纲复制到kimi中生成PPT kimi&#xff1a;https://kimi.moonshot.cn/...

JavaWeb学习-Mybatis(增删改查)

(一)Mybatis入门程序 1.创建springboot工程,并导入 mybatis的起步依赖、mysql的驱动包。(项目工程创建完成后,自动在pom.xml文件中,导入Mybatis依赖和MySQL驱动依赖) <dependencies> <!-- mybatis起步依赖 --> <dependency> …...

软考高项(二十四)法律法规和标准规范 ★重点集萃★

&#x1f451; 个人主页 &#x1f451; &#xff1a;&#x1f61c;&#x1f61c;&#x1f61c;Fish_Vast&#x1f61c;&#x1f61c;&#x1f61c; &#x1f41d; 个人格言 &#x1f41d; &#xff1a;&#x1f9d0;&#x1f9d0;&#x1f9d0;说到做到&#xff0c;言出必行&am…...

Django中select_related 的作用

Django中这句代码Dynamic.objects.select_related(song)是什么意思&#xff1f; 在 Django 中&#xff0c;这句代码&#xff1a; Dynamic.objects.select_related(song) 的作用是 在查询 Dynamic 模型的同时&#xff0c;预加载 song 关联的外键对象&#xff0c;从而减少数据…...

vscode无法ssh连接远程机器解决方案

远程服务器配置问题 原因&#xff1a;远程服务器的 SSH 服务配置可能禁止了 TCP 端口转发功能&#xff0c;或者 VS Code Server 在远程服务器上崩溃。 解决办法 检查 SSH 服务配置&#xff1a;登录到远程服务器&#xff0c;打开 /etc/ssh/sshd_config 文件&#xff0c;确保以下…...

计算机组成原理——中央处理器(九)

在每一个清晨醒来&#xff0c;你都有一个全新的机会去塑造你的世界。无论昨日经历了多少风雨&#xff0c;今天的你依旧可以启航向梦想的彼岸。生活或许会给你设置障碍&#xff0c;但请相信&#xff0c;这些都是通往成功的垫脚石。不要让短暂的困境遮蔽了你的视野&#xff0c;因…...

网页版贪吃蛇小游戏开发HTML实现附源码!

项目背景 贪吃蛇是一款经典的休闲小游戏&#xff0c;因其简单易玩的机制和丰富的变形而深受玩家喜爱。本次开发目标是实现一款网页版贪吃蛇小游戏&#xff0c;并通过前端与后端结合的方式&#xff0c;提供一个流畅的在线体验。 实现过程 游戏逻辑设计 蛇的移动&#xff1a;…...

基于java ssm springboot选课推荐交流平台系统设计和实现

基于JavaWeb开发的 &#x1f345; 作者主页 网顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 &#x1f4dd; &#x1f680;&…...

Sigma-Aldrich化学品安全技术说明书(SDS)查询教程

在当今的现代工业体系里&#xff0c;化学品的应用极为广泛&#xff0c;贯穿于众多行业的生产环节。以电子、皮革、玩具、工艺品、家具制造等行业为例&#xff0c;有机溶剂的使用频率颇高&#xff0c;这虽极大地推动了生产的发展&#xff0c;却也埋下了风险隐患。在这些企业中&a…...

嵌入式实训室解决方案(2025年最新版)

一、背景概述 随着信息技术的迅猛进步&#xff0c;嵌入式系统已成为智能化设备与应用的核心驱动力&#xff0c;引领产业变革与创新。其应用范围广泛&#xff0c;涵盖智能家居、智能医疗、工业控制、交通及网络通信等领域&#xff0c;是信息化与智能化转型的关键。在此背景下&am…...

Spring Cloud — 深入了解Eureka、Ribbon及Feign

Eureka 负责服务注册与发现&#xff1b;Ribbon负责负载均衡&#xff1b;Feign简化了Web服务客户端调用方式。这三个组件可以协同工作&#xff0c;共同构建稳定、高效的微服务架构。 1 Eureka 分布式系统的CAP定理&#xff1a; 一致性&#xff08;Consistency&#xff09;&am…...

全排列(力扣46)

这道题让我们求这个集合有多少种排列方式&#xff0c;那么与之前组合问题的不同就在于要考虑元素之间的顺序了&#xff0c;所以每一层递归的or循环的起始值无需变量控制&#xff0c;都从0开始。但是一个排列中不能出现相同元素&#xff0c;所以别忘了去重&#xff0c;这里的去重…...

Mac部署Jenkins 一

Mac部署Jenkins 一 一.Jenkins 部署依赖 JDK 环境 查看 Mac JDK 环境&#xff0c;如果没有安装&#xff0c;先安装 打开终端输入命令:java -version Mac安装配置 JDK 二. 检查 HomeBrew 安装 检查 HomeBrew 是否安装&#xff0c;终端输入命令:brew -v Mac安装HomeBrew …...