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 modles

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var db *gorm.DB
var err error

func init() {
	dsn := "root:123456789@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	// Globally mode
	db, 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 modles

type User struct { 
	// 默认表名是 users
	Id int
	Username string
	Age int1
	Email string
	AddTime 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 1
	fmt.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 1
	c.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 = 22
	models.DB.Debug().Save(&user)
	// UPDATE `user` SET `user_name`='haha',`age`=22,`email`='ychag@example.com',`add_time`=1708047687 WHERE `id` = 1
	c.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.User
	models.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 > 0
	c.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 = 5
	models.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 NULL
	models.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 NULL

	c.JSON(200, gin.H{
		"success": true,
		"result":  article,
	})
}

指定字段查询

func (a ArticleController) GetOne(c *gin.Context) {
	article := &[]models.Article{}

	// 查询文章的id 和 title
	models.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 desc
	c.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 1
	c.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 NULL

	c.JSON(200, gin.H{
		"success": true,
		"result":  article,
	})
}

获取不同值

func (a ArticleController) GetDistinct(c *gin.Context) {
	article := &[]models.Article{}

	// 选择不同的 title
	models.DB.Debug().Distinct("title").Find(&article)
	// SELECT DISTINCT `title` FROM `articles` WHERE `articles`.`deleted_at` IS NULL
	c.JSON(200, gin.H{
		"success": true,
		"result":  article,
	})
}

Scan

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

type Result struct {
	AuthorId int
	Title    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://www.mfbz.cn/a/600612.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu18.04设置SSH密钥登录

我们一般使用 VSCode 、MobaXterm、PuTTY等 SSH 客户端来远程管理 Linux 服务器。但是&#xff0c;一般的密码方式登录&#xff0c;容易有密码被暴力破解的问题。所以&#xff0c;一般我们会将 SSH 的端口设置为默认的 22 以外的端口&#xff0c;或者禁用 root 账户登录。但是即…

解决ImportError: cannot import name ‘xxx‘ from partially initialized module xxx

python项目中某个文件名与需要引入的module中的文件名相同时&#xff0c;可能出现循环引用的情况&#xff0c;此时会报错ImportError: cannot import name ‘xxx‘ from partially initialized module xxx。 所以把项目文件中涉及 报错内容的python文件名 修改即可。 如我的…

剧本杀小程序,为商家带来更多收益

剧本杀作为一种社交类游戏&#xff0c;关注度越来越高&#xff0c;目前&#xff0c;市场上剧本杀依然呈现上升发展趋势。 不过当下&#xff0c;在剧本杀市场中&#xff0c;大部分商家都开始使用小程序管理运营剧本杀。相对于线下剧本杀&#xff0c;线上剧本杀小程序便于商家管…

「51媒体」企业单位新闻稿件考核,怎么发布

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 电力税务企事业单位部门等单位提供了新闻稿件&#xff0c;如何在一些重点媒体进行宣发呢&#xff1a; 精准锁定发布媒体 了解考核要求&#xff1a;仔细阅读宣传任务名单&#xff0c;了解…

探索GitHub上的GPTs项目:泄露和被破解的GPT提示

GPTs项目是一个在GitHub上由用户linexjlin发起的开源项目&#xff0c;专注于提供泄露的GPT&#xff08;生成式预训练转换器&#xff09;提示。这些提示用于指导和优化AI模型的输出&#xff0c;进而提升代码生成的质量和效率。项目页面提供了丰富的功能和资源&#xff0c;旨在帮…

JavaScript余数运算符

console.log(5 % 2); //5 2 * 2 1 console.log(8 % 3); //8 2 * 3 2 console.log(6 % 2); //6 2 * 3 0 console.log(7 % 2); //7 2 * 3 1● 我们可以利用这个特性来判断一个数是奇数还是偶数 const isEven n >n % 2 0 ? console.log(${n}是偶数) : console.…

Python扩展模块的开发

有关python C扩展开发的教程可以参考概述 — Python 3.12.3 文档。项目已经发布至python官方的pypi里了。具体详情请见AdroitFisherman PyPI。目前该项目还处在测试阶段。尚有部分模块需要开发和测试。 项目结构 项目结构见下图&#xff1a; 代码展示与说明 以单链表(SingleL…

【go项目01_学习记录04】

学习记录 1 集成 Gorilla Mux1.1 为什么不选择 HttpRouter&#xff1f;1.2 安装 gorilla/mux1.3 使用 gorilla/mux1.4 迁移到 Gorilla Mux1.4.1 新增 homeHandler1.4.2 指定 Methods () 来区分请求方法1.4.3 请求路径参数和正则匹配1.4.4 命名路由与链接生成 1 集成 Gorilla Mu…

【Linux网络】PXE批量网络装机

目录 一、系统装机 1.1 三种引导方式 1.2 系统安装过程 1.3 四大重要文件 二、PXE 2.1 PXE实现原理 2.2 PXE手动搭建过程 2.3 kickstart配合pxe完成批量自动安装 一、系统装机 1.1 三种引导方式 硬盘光驱(U盘)网络启动 1.2 系统安装过程 加载boot loader加载启动安…

借势母亲节h5小游戏的作用是什么

企业商家往往喜欢借势节日开展营销&#xff0c;母亲节作为5月的重要节日自然不可错过&#xff0c;不同行业商家都有自己开展互动想要实现的效果&#xff0c;如品牌宣传曝光、引流及渠道跳转等。 基于微信社交属性&#xff0c;有利于品牌发展&#xff0c;在【雨科】平台拥有多款…

SparkSQL优化

SparkSQL优化 优化说明 缓存数据到内存 Spark SQL可以通过调用spark.sqlContext.cacheTable("tableName") 或者dataFrame.cache()&#xff0c;将表用一种柱状格式&#xff08; an inmemory columnar format&#xff09;缓存至内存中。然后Spark SQL在执行查询任务…

有什么方便实用的成人口语外教软件?6个软件教你快速进行口语练习

有什么方便实用的成人口语外教软件&#xff1f;6个软件教你快速进行口语练习 口语能力在语言学习中占据着重要的位置&#xff0c;因为它直接关系到我们与他人进行交流和沟通的效果。为了提高口语能力&#xff0c;很多成人选择通过外教软件进行口语练习&#xff0c;这些软件提供…

【强训笔记】day13

NO.1 代码实现&#xff1a; #include <iostream>#include<string>using namespace std;int n,k,t; string s;int func() {int ret0;for(int i0;i<n;i){char chs[i];if(chL) ret-1;else{if(i-1>0&&i-2>0&&s[i-1]W&&s[i-2]W) retk…

基于Springboot 的 Excel表格的导入导出

首先 &#xff0c;引入相关依赖EasyPOI <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.4.0</version></dependency> 编写实体类&#xff1a; Data AllArgs…

Java 框架安全:Struts2 漏洞序列测试.

什么是 Struts2 框架 Struts 2 是一个用于创建企业级 Java 应用程序的开源框架。它是一个 MVC&#xff08;模型-视图-控制器&#xff09;框架&#xff0c;用于开发基于 Java EE&#xff08;Java Platform, Enterprise Edition&#xff09;的 Web 应用程序。Struts 2 主要解决…

ROS机器人实用技术与常见问题解决

问题速查手册&#xff08;时实更新&#xff09;更加全面丰富的问题手册记录 1.机器人使用GPARTED挂载未分配空间 需要在图型界面下操作&#xff0c;建议使用no machine连接 安装gparted磁盘分区工具, sudo apt-get install gparted -y 启动软件 sudo gparted 点击磁盘/内存…

C# OpenCvSharp 图片找茬

C# OpenCvSharp 图片找茬 目录 效果 项目 代码 下载 效果 项目 代码 using OpenCvSharp; using System; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; namespace OpenCvSharp_Demo { public partial class Form1 : Form { …

1688快速获取整店铺列表 采集接口php Python

在电子商务的浪潮中&#xff0c;1688平台作为中国领先的批发交易平台&#xff0c;为广大商家提供了一个展示和销售商品的广阔舞台&#xff1b;然而&#xff0c;要在众多店铺中脱颖而出&#xff0c;快速获取商品列表并进行有效营销是关键。 竞争对手分析 价格比较&#xff1a;…

mysql5.7数据库安装及性能测试

mysql5.7数据库安装及性能测试 记录Centos7.9下安装mysql 5.7并利用benchmark工具简单测试mysql的性能。 测试机&#xff1a;centos7.9 配置&#xff1a;4C8G40G 1. 下安装mysql5.7 安装mysql5.7&#xff1a; # 通过官方镜像源安装$ wget http://dev.mysql.com/get/mysql57-com…

pandas索引

pandas索引 一、索引1.1 建立索引1.2 重置索引1.3 索引类型1.4 索引的属性1.5 索引的操作 一、索引 1.1 建立索引 建立索引可以在数据读取加载中指定索引&#xff1a; import pandas as pd df pd.read_excel(team.xlsx, index_colname) # 将name列设置为索引 df.head()效…
最新文章