GORM 与 MySQL(一)

GORM 操作 Mysql 数据库(一)

温馨提示:以下关于 GORM 的使用,是基于 Gin 框架的基础上,如果之前没有了解过 Gin 可能略微困难。

GORM 介绍

GORM 是 Golang 的一个 orm 框架。简单说,ORM 就是通过实例对象的语法,完成关系型
数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写。使用 ORM
框架可以让我们更方便的操作数据库。

GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server。

GORM 特性

  • 全功能 ORM
  • 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
  • Create,Save,Update,Delete,Find 中钩子方法
  • 支持 Preload、Joins 的预加载
  • 事务,嵌套事务,Save Point,Rollback To Saved Point
  • Context、预编译模式、DryRun 模式
  • 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进
    行 CRUD
  • SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询
  • 复合主键,索引,约束
  • Auto Migration
  • 自定义 Logger
  • 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
  • 每个特性都经过了测试的重重考验
  • 开发者友好

GORM 前置

安装

如果使用 go mod 管理项目的话可以忽略此步骤

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

连接数据库

在 models 下面新建 core.go ,建立数据库链接

package modlesimport ("gorm.io/driver/mysql""gorm.io/gorm"
)var db *gorm.DB
var err errorfunc init() {dsn := "root:123456789@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"// Globally modedb, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {panic(err)}
}

定义操作模型

在实际项目中定义数据库模型注意以下几点:

1、结构体的名称必须首字母大写 ,并和数据库表名称对应。

例如:表名称为 user 结构体名称定义成 User,表名称为 article_cate 结构体名称定义成 ArticleCate

2、结构体中的字段名称首字母必须大写,并和数据库表中的字段一一对应。

例如:下面结 构体中的 Id 和数据库中的 id 对应,Username 和数据库中的 username 对应,Age 和数据库中 的 age 对应,Email 和数据库中的 email 对应,AddTime 和数据库中的 add_time 字段对应。

3、默认情况表名是结构体名称的复数形式。

如果我们的结构体名称定义成 User,表示这个 模型默认操作的是 users 表。

4、我们可以使用结构体中的自定义方法 TableName 改变结构体的默认表名称,如下:

func (User) TableName() string { return "user"
}

表示把 User 结构体默认操作的表改为 user 表。

定义 User 模型:

package modlestype User struct { // 默认表名是 usersId intUsername stringAge int1Email stringAddTime int
}func(User) TableName() string {return "user"
}

gorm.Model 模型

GORM 定义一个 gorm.Model 结构体,其包括字段 IDCreatedAtUpdatedAtDeletedAt

type Model struct {
ID uint `gorm:"primaryKey"` 
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}

GORM CRUD

注意:我们在关键词之前加上 DEBUG 方法可以获取执行的 SQL 语句。

增加

我们一般使用 Create 方法构建,增加成功后会返回刚才增加的记录。

func (con UserController) Add(c *gin.Context) {// 单数据user := models.User{UserName: "ypb",Age:      20,Email:    "ychag@example.com",AddTime:  int(time.Now().Unix()),}// 批量数据users := []*models.User{{UserName: "yxc", Age: 20, Email: "ychag@example.com", AddTime: int(time.Now().Unix())},{UserName: "zmz", Age: 20, Email: "zmzag@example.com", AddTime: int(time.Now().Unix())},}result := models.DB.Create(&users) // 通过指针创建if result.RowsAffected > 1 {fmt.Println(user.Id)}fmt.Println(result.RowsAffected)fmt.Println(user.Id)c.String(200, "add ok")
}

查找

GORM 提供了 FirstTakeLastFind 方法,以便从数据库中检索对象。

不指定条件查询
func (con UserController) Get(c *gin.Context) {user := models.User{}// First 获取第一条记录(主键升序)models.DB.Debug().First(&user)// SELECT * FROM `user` ORDER BY `user`.`id` LIMIT 1fmt.Println(user.Id)// Last 获取最后一条记录(主键降序)models.DB.Debug().Last(&user)fmt.Println(user.Id)// SELECT * FROM `user` WHERE `user`.`id` = 1 ORDER BY `user`.`id` DESC LIMIT 1// Find 获取所有记录users := []models.User{}models.DB.Debug().Find(&users)//SELECT * FROM `user`c.JSON(200, gin.H{"message": "get ok","result":  users,})
}
指定条件查询
func (con UserController) GetByCondition(c *gin.Context) {user := models.User{}// Where 指定查询条件models.DB.Debug().Where("user_name = ?", "yxc").First(&user)//  SELECT * FROM `user` WHERE user_name = 'yxc' ORDER BY `user`.`id` LIMIT 1c.JSON(200, gin.H{"message": "get ok","result":  user,})
}

修改

字段条件查询修改
func (con UserController) Update(c *gin.Context) {// 首先获取数据user := models.User{Id: 1}models.DB.Debug().Find(&user)//  SELECT * FROM `user` WHERE `user`.`id` = 1// 然后更新数据user.UserName = "haha"user.Age = 22models.DB.Debug().Save(&user)// UPDATE `user` SET `user_name`='haha',`age`=22,`email`='ychag@example.com',`add_time`=1708047687 WHERE `id` = 1c.String(200, "update ok")
}

where 条件查询修改
func (con UserController) UpdateByCondition(c *gin.Context) {// Where 条件更新单列数据models.DB.Debug().Model(&models.User{}).Where("id = ?", 1).Update("age", 15)// UPDATE `user` SET `age`=15 WHERE id = 1// Where 条件更新多列数据var users []models.Usermodels.DB.Debug().Model(&users).Where("user_name = ?", "yxc").Updates(models.User{UserName: "yxc", Age: 22})// UPDATE `user` SET `user_name`='yxc',`age`=22 WHERE user_name = 'yxc'c.String(200, "update ok")
}

删除

删除单行数据:

func (con UserController) Delete(c *gin.Context) {// Where 条件删除单条数据models.DB.Debug().Where("user_name = ?", "haha").Delete(&models.User{})// DELETE FROM `user` WHERE user_name = 'haha'
}

删除所有数据:

func (con UserController) DeleteAll(c *gin.Context) {users := []models.User{}models.DB.Debug().Where("id > ?", 0).Delete(&users)//  SELECT * FROM `user` WHERE id > 0c.JSON(200, gin.H{"message": "delete ok",})
}

GORM 查询语句详解

where 及 操作符

func (a ArticleController) Get(c *gin.Context) {article := &[]models.Article{}//  < 小于号, 选择所有id小于3的文章models.DB.Debug().Where("id < ?", 3).Find(&article)//  SELECT * FROM `articles` WHERE id < 3 AND `articles`.`deleted_at` IS NULL// > 大于号, 选择所有id大于5的文章var id = 5models.DB.Debug().Where("id > ?", id).Find(&article)// SELECT * FROM `articles` WHERE id > 5 AND `articles`.`deleted_at` IS NULL// AND 操作符, 选择所有id大于1且小于5的文章models.DB.Debug().Where("id > ? and id < ?", 1, 5).Find(&article)//  SELECT * FROM `articles` WHERE (id > 1 AND id < 5) AND `articles`.`deleted_at` IS NULL// in 操作符, 选择所有id大于2且小于5的文章models.DB.Debug().Where("id in ?", []int{3, 4}).Find(&article)//SELECT * FROM `articles` WHERE id in (3,4) AND `articles`.`deleted_at` IS NULL// like 操作符, 选择 文章标题含 go 的文章models.DB.Debug().Where("title like ?", "%go%").Find(&article)// SELECT * FROM `articles` WHERE title like '%go%' AND `articles`.`deleted_at` IS NULL// between and 操作符, 选择文章id在 1 到 5 之间的文章models.DB.Debug().Where("id between ? and ?", 1, 5).Find(&article)// SELECT * FROM `articles` WHERE (id between 1 and 5) AND `articles`.`deleted_at` IS NULL// or 操作符, 选择文章id在 1 到 5 之间的文章或 id 等于 6 的文章models.DB.Debug().Where("id between ? and ? or id = ?", 1, 5, 6).Find(&article)//SELECT * FROM `articles` WHERE (id between 1 and 5 or id = 6) AND `articles`.`deleted_at` IS NULLmodels.DB.Debug().Where("id between ? and ?", 1, 5).Or("id = ?", 6).Find(&article)//SELECT * FROM `articles` WHERE ((id between 1 and 5) OR id = 6) AND `articles`.`deleted_at` IS NULLc.JSON(200, gin.H{"success": true,"result":  article,})
}

指定字段查询

func (a ArticleController) GetOne(c *gin.Context) {article := &[]models.Article{}// 查询文章的id 和 titlemodels.DB.Debug().Select("id, title").First(&article)c.JSON(200, gin.H{"success": true,"result":  article,})
}

排序

func (a ArticleController) GetOne(c *gin.Context) {article := &[]models.Article{}// 按 ID 降序排序models.DB.Debug().Order("id desc").Find(&article)// SELECT * FROM `articles` WHERE `articles`.`deleted_at` IS NULL ORDER BY id desc// 按 ID 升序排序 按 author_id 降序排序models.DB.Debug().Order("id asc, author_id desc").Find(&article)// SELECT * FROM `articles` WHERE `articles`.`deleted_at` IS NULL ORDER BY id asc, author_id descc.JSON(200, gin.H{"success": true,"result":  article,})
}

Limit, Offset

func (a ArticleController) GetOne(c *gin.Context) {article := &[]models.Article{}// 查询ID大于1的文章, 限制1条数据 (随机一条)models.DB.Debug().Where("id > ?", 1).Limit(1).Find(&article)// SELECT * FROM `articles` WHERE id > 1 AND `articles`.`deleted_at` IS NULL LIMIT 1// 实现 跳过一条数据查询2条数据 (分页)models.DB.Debug().Where("id > ?", 1).Offset(1).Limit(1).Find(&article)// SELECT * FROM `articles` WHERE id > 1 AND `articles`.`deleted_at` IS NULL LIMIT 1 OFFSET 1c.JSON(200, gin.H{"success": true,"result":  article,})
}

获取总数

func (a ArticleController) GetSum(c *gin.Context) {article := &[]models.Article{}var sum int64// 获取author_id等于1的文章的数量models.DB.Debug().Where("author_id = ?", 1).Find(&article).Count(&sum)//SELECT count(*) FROM `articles` WHERE author_id = 1 AND `articles`.`deleted_at` IS NULLc.JSON(200, gin.H{"success": true,"result":  article,})
}

获取不同值

func (a ArticleController) GetDistinct(c *gin.Context) {article := &[]models.Article{}// 选择不同的 titlemodels.DB.Debug().Distinct("title").Find(&article)// SELECT DISTINCT `title` FROM `articles` WHERE `articles`.`deleted_at` IS NULLc.JSON(200, gin.H{"success": true,"result":  article,})
}

Scan

Scan 可以将结果绑定到一个结构体上。

type Result struct {AuthorId intTitle    string
}func (a ArticleController) GetScan(c *gin.Context) {var result []Result//models.DB.Table("articles").Select("author_id, title").Scan(&result)models.DB.Raw("SELECT author_id, title FROM articles").Scan(&result)fmt.Println(result)
}

原生 SQL 和 生成器

1、使用原生 sql 删除 user 表中的一条数据

result := models.DB.Exec("delete from user where id=?", 3) 
fmt.Println(result.RowsAffected)

2、使用原生 sql 修改 user 表中的一条数据

result := models.DB.Exec("update user set username=? where id=2", "哈哈") 
fmt.Println(result.RowsAffected)

3、查询 uid = 2 的数据

var result models.User
models.DB.Raw("SELECT * FROM user WHERE id = ?", 2).Scan(&result) 
fmt.Println(result)

4、查询 User 表中所有的数据

var result []models.User
models.DB.Raw("SELECT * FROM user").Scan(&result) 
fmt.Println(result)

5、统计 user 表的数量

var count int
row := models.DB.Raw("SELECT count(1) FROM user").Row(&count ) 
row.Scan(&count)

结尾

本次我们了解了 GORM 的基本用法,主要设计到对一个表的操作。但是在实际的业务中,我们往往需要从多张表获取数据。

下次,我们将去了解 GORM 中多表操作。

下次见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3016340.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

ASP.NET网上鲜花销售系统的设计

摘 要 本系统实现了一般电子商务所具备的功能&#xff0c;如商品浏览、用户登录注册、网上与购物、结算、后台数据库管理等&#xff0c;利用这些功能可以对鲜花销售信息进行较好的管理。 网上鲜花销售系统的使用者主要是客户和销售管理者&#xff0c;对于客户来说&#xff0…

Qt | QComboBox(组合框)

01、上节回顾 Qt 基础教程合集02、QComBox 一、QComboBox 类(下拉列表、组合框) 1、QComboBox 类是 QWidget 类的直接子类,该类实现了一个组合框 2、QComboBox 类中的属性 ①、count:const int 访问函数:int count() const; 获取组合框中的项目数量,默认情况下,对于空…

java入门详细教程——day01

目录 1. Java入门 1.1 Java是什么&#xff1f; 1.2 Java语言的历史 1.3 Java语言的分类 1.4 Java语言的特点 1.4.1 先编译再解释运行 1.4.2 跨平台 1.5 JRE和JDK&#xff08;记忆&#xff09; 1.6 JDK的下载和安装&#xff08;应用&#xff09; 1.6.1 下载 1.6.2 安…

新手做抖音小店多久能出单?新手抖音小店出单秘籍!出单教程必看

大家好&#xff0c;我是电商花花。 现阶段还是有很多朋友加入到抖音电商行业&#xff0c;因为抖音小店上还隐藏很多的红利和市场&#xff0c;很多新手开店后第一个问题就是&#xff0c;店铺开通后&#xff0c;一般多久能出单&#xff1f; 多久能出单&#xff0c;其实更看重的…

并发编程之阻塞队列BlockingQueue实战及其原理分析

1. 阻塞队列介绍 1.1 队列 是限定在一端进行插入&#xff0c;另一端进行删除的特殊线性表。 先进先出(FIFO)线性表。 允许出队的一端称为队头&#xff0c;允许入队的一端称为队尾。

分布式与一致性协议之ZAB协议(五)

ZAB协议 ZAB集群如何从故障中恢复 如果我们想把ZAB集群恢复到正常状态&#xff0c;那么新领导者就必须确立自己的领导关系&#xff0c;成为唯一有效的领导者&#xff0c;然后作为主节点"领导"各备份节点一起处理读写请求 如何确立领导关系 前面提到&#xff0c;选…

5000A信号发生器使用方法

背景 gnss工作需要使用的5000A&#xff0c;所以做成文档&#xff0c;用于其他员工学习。 下载星历数据 https://cddis.nasa.gov/archive/gnss/data/daily/2024/brdc/ 修改daily中的年份&#xff0c;就可以获取相关截至时间的星历数据 brcd数据格式 第一行记录了卫星的PRN号&a…

Java毕业设计 基于SpringBoot vue企业信息管理系统

Java毕业设计 基于SpringBoot vue企业信息管理系统 SpringBoot 企业信息管理系统 功能介绍 员工&#xff1a;登录 个人中心 修改密码 个人信息 会议管理 公告管理 个人计划管理 通讯录管理 外出登记管理 请假管理 上下班打卡管理 管理员&#xff1a;登录 个人中心 修改密码 …

流量暴涨!抖音+快手+小红书获客攻略!

在数字营销的海洋中&#xff0c;抖音、快手和小红书无疑是三座巨大的灯塔&#xff0c;照亮了品牌和个人获取流量的道路。这些平台不仅拥有庞大的用户基础&#xff0c;而且其独特的算法和社交特性让获客变得更加高效而精准。接下来&#xff0c;让我们深入探讨如何通过这三个平台…

Eplan带你做项目——如何实现项目的交付

前言 Eplan作为一款专业的电气工程设计软件&#xff0c;不仅在设计阶段为电气工程师提供了强大的绘图、计算、仿真等功能&#xff0c;还具备丰富的数据管理与交换能力&#xff0c;能够便捷、准确地导出软件设计、生产制造所需的数据&#xff0c;实现电气设计与软件设计、生产制…

《QT实用小工具·五十九》随机图形验证码,带有一些可人的交互与动画

1、概述 源码放在文章末尾 该项目实现了可交互的动画验证码控件&#xff0c;趣味性十足&#xff1a; 字符变换动画 噪音动画 可拖动交互 项目demo演示如下所示&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef CAPTCHAMOVABLELABEL_H #define CAPTCHAMOVABLELABEL…

Kubernetes 教程:在 Containerd 容器中使用 GPU

原文链接:Kubernetes 教程:在 Containerd 容器中使用 GPU 云原生实验室本文介绍了如何在使用 Containerd 作为运行时的 Kubernetes 集群中使用 GPU 资源。https://fuckcloudnative.io/posts/add-nvidia-gpu-support-to-k8s-with-containerd/ 前两天闹得沸沸扬扬的事件不知道…

技术速递|使用 .NET 为 Microsoft AI 构建可扩展网关

作者&#xff1a;Kara Saucerman 排版&#xff1a;Alan Wang Microsoft AI 团队构建了全面的内容、服务、平台和技术&#xff0c;以便消费者在任何设备上、任何地方获取他们想要的信息&#xff0c;并为企业改善客户和员工的体验。我们的团队支持多种体验&#xff0c;包括 Bing、…

全栈开发之路——前端篇(6)生命周期和自定义hooks

全栈开发一条龙——前端篇 第一篇&#xff1a;框架确定、ide设置与项目创建 第二篇&#xff1a;介绍项目文件意义、组件结构与导入以及setup的引入。 第三篇&#xff1a;setup语法&#xff0c;设置响应式数据。 第四篇&#xff1a;数据绑定、计算属性和watch监视 第五篇 : 组件…

详细讲解lua中string.gsub的使用

string.gsub 是 Lua 标准库中的一个函数&#xff0c;用于全局替换字符串中的某些部分。string.gsub 是 Lua 中非常实用的一个函数&#xff0c;它可以用来进行字符串的处理和替换操作。 它的基本语法如下&#xff1a; string.gsub(s, pattern, replacement [, n])s 是要处理的…

HarmonyOS实战开发教程-如何开发一个2048游戏

今天为大家分享的是2048小游戏&#xff0c;先看效果图&#xff1a; 这个项目对于新手友友来说可能有一点难度&#xff0c;但是只要坚持看完一定会有收获。因为小编想分享的并不局限于ArkTs语言&#xff0c;而是编程思想。 这个游戏的基本逻辑是初始化一个4乘4的数组&#xff…

深度学习模型训练套路与验证套路以及如何使用GPU进行模型训练

完整的模型训练套路&#xff1a;代码模板 数据集以经典的 CIFAR10 为例。 这个例子是很简单的&#xff0c;可能不太实用&#xff0c;但重点是通过这个例子掌握一种模型训练的写法套路&#xff0c;因此很有必要学习。 import torch.optim import torchvision from torch impo…

JavaScript异步编程——02-Ajax入门和发送http请求

同步和异步回顾 同步和异步的简单理解 同步&#xff1a;必须等待前面的任务完成&#xff0c;才能继续后面的任务。 异步&#xff1a;不受当前任务的影响。 拿排队举例&#xff1a; 同步&#xff1a;在银行排队时&#xff0c;只有等到你了&#xff0c;才能够去处理业务。 异…

【C++泛型编程】(二)标准模板库 STL

文章目录 标准模板库 STL容器算法迭代器仿函数/函数对象适配器分配器示例 标准模板库 STL C 的标准模板库&#xff08;Standard Template Library&#xff0c;STL&#xff09;旨在通过模板化的设计&#xff0c;提供一种通用的编程模式&#xff0c;使程序员能方便地实现和扩展各…

数据仓库项目---Day01

文章目录 框架的安装包数据仓库概念项目需求及架构设计项目需求分析项目框架技术选型系统数据流程设计框架版本选型集群资源规划设计 数据生成模块数据埋点主流埋点方式埋点数据上报时机 服务器和JDK准备搭建三台Linux虚拟机(VMWare)编写集群分发脚本xsyncSSH无密登录配置JDK准…