13-Gin 中使用 GORM 操作 mysql 数据库 --[Gin 框架入门精讲与实战案例]

GORM 简单介绍

GORM(Golang ORM)是Go语言(Golang)中一个非常流行的对象关系映射(ORM)库,它旨在简化数据库操作。通过GORM,开发者可以使用结构体和接口来代替SQL语句进行数据库的增删改查等操作,从而提高开发效率并减少错误。

GORM 的主要特点

  1. 支持多种数据库:GORM 支持 MySQL、PostgreSQL、SQLite3、SQL Server 等多种主流的关系型数据库。
  2. 自动迁移:GORM 可以根据结构体定义自动生成或更新数据库表结构。
  3. 关联管理:支持一对多、多对多等复杂的数据模型关联关系,并提供便捷的方法来操作这些关联。
  4. 预加载:可以预先加载相关联的数据,减少 N+1 查询问题。
  5. 事务处理:内置对事务的支持,确保数据的一致性和完整性。
  6. 钩子函数:允许在创建、更新、删除记录前后执行自定义逻辑。
  7. 插件系统:拥有丰富的插件生态系统,方便扩展功能。

安装 GORM

要开始使用 GORM,首先需要安装它。你可以通过 go get 命令来安装:

go get -u gorm.io/gorm

此外,还需要安装对应数据库驱动,例如对于 PostgreSQL:

go get -u gorm.io/driver/postgres

基本用法示例

下面是一个简单的例子,展示如何连接到数据库以及基本的CRUD操作:

导入包
import (
  "gorm.io/driver/sqlite"
  "gorm.io/gorm"
)
连接到数据库
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
  panic("failed to connect database")
}
定义模型
type Product struct {
  gorm.Model
  Code  string
  Price uint
}
自动迁移
db.AutoMigrate(&Product{})
创建记录
db.Create(&Product{Code: "D42", Price: 100})
查询记录
var product Product
db.First(&product, 1) // 根据主键查询第一条记录
db.First(&product, "code = ?", "D42") // 根据条件查询第一条记录
更新记录
db.Model(&product).Update("Price", 200)
删除记录
db.Delete(&product, 1) // 根据主键删除记录

总结

GORM 是一个强大且易于使用的 ORM 库,它为 Go 开发者提供了高效的数据库交互方式。通过其简洁的 API 和灵活的功能,可以大大简化应用程序中的数据持久化层代码编写。如果你正在寻找一种方法来快速构建基于 Go 的应用,并且希望避免直接编写复杂的 SQL 语句,那么 GORM 可能正是你需要的工具。

Gin 中使用 GORM

在 Gin 框架中使用 GORM 来操作 MySQL 数据库,首先你需要确保安装了必要的依赖包,并配置好数据库连接。下面我将指导你如何设置和使用 GORM 连接 MySQL 数据库。

1. 安装依赖

首先,确保你的项目中包含了 Gin 和 GORM 的 MySQL 驱动。你可以通过以下命令来安装这些依赖:

go get -u github.com/gin-gonic/gin
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

2. 配置数据库连接

接下来,在你的 Go 程序中配置 MySQL 数据库的连接。这通常包括设置数据库 URL 和初始化 GORM。

示例代码 (main.go)
package main

import (
	"fmt"
	"log"

	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

// Product 是一个示例模型
type Product struct {
	gorm.Model
	Code  string
	Price uint
}

func main() {
	// MySQL 数据库连接字符串
	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 {
		log.Fatal("failed to connect database")
	}

	// 自动迁移表结构
	db.AutoMigrate(&Product{})

	// 创建 Gin 路由器
	router := gin.Default()

	// 设置路由处理函数
	router.GET("/products", func(c *gin.Context) {
		var products []Product
		if result := db.Find(&products); result.Error != nil {
			c.JSON(500, gin.H{"error": "无法获取产品列表"})
			return
		}
		c.JSON(200, products)
	})

	router.POST("/products", func(c *gin.Context) {
		var product Product
		if err := c.ShouldBindJSON(&product); err != nil {
			c.JSON(400, gin.H{"error": err.Error()})
			return
		}
		if result := db.Create(&product); result.Error != nil {
			c.JSON(500, gin.H{"error": "创建产品失败"})
			return
		}
		c.JSON(201, product)
	})

	// 启动服务器
	if err := router.Run(":8080"); err != nil {
		log.Fatal(err)
	}
}

3. 数据库连接字符串

在上面的代码中,dsn 变量包含了 MySQL 数据库的连接字符串。格式如下:

user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local
  • user:MySQL 用户名。
  • password:MySQL 密码。
  • 127.0.0.1:3306:MySQL 服务器地址和端口(默认为 3306)。
  • dbname:要连接的数据库名称。
  • charset=utf8mb4&parseTime=True&loc=Local:一些额外的参数,用于指定字符集、时间解析和时区。

请根据实际情况修改这些值以匹配你的 MySQL 配置。

4. 测试 API

启动应用程序后,你可以使用工具如 Postman 或 curl 来测试定义的 API 端点。例如,向 /products 发送 GET 请求以获取所有产品的列表,或者发送 POST 请求并附带 JSON 数据来创建新产品。

总结

通过上述步骤,你已经成功地在 Gin 框架中集成了 GORM 并连接到了 MySQL 数据库。这个基础设置可以帮助你快速开始构建基于 RESTful API 的 Web 应用程序。

Gin GORM CURD

在 Gin 框架中使用 GORM 进行 MySQL 数据库的 CRUD(创建、读取、更新、删除)操作,可以通过定义模型结构体并编写相应的路由处理函数来实现。下面我将详细说明如何完成这些操作,并提供完整的代码示例。

1. 安装依赖

首先,确保你的项目中包含了 Gin 和 GORM 的 MySQL 驱动。你可以通过以下命令来安装这些依赖:

go get -u github.com/gin-gonic/gin
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

2. 配置数据库连接和初始化

接下来,在你的 Go 程序中配置 MySQL 数据库的连接,并初始化 GORM。

示例代码 (main.go)
package main

import (
	"fmt"
	"log"

	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

// Product 是一个示例模型
type Product struct {
	gorm.Model
	Code  string `json:"code" gorm:"unique"`
	Price uint   `json:"price"`
}

var db *gorm.DB

func init() {
	// MySQL 数据库连接字符串
	dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"

	var err error
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatal("failed to connect database")
	}

	// 自动迁移表结构
	db.AutoMigrate(&Product{})
}

func main() {
	// 创建 Gin 路由器
	router := gin.Default()

	// 设置路由处理函数
	router.GET("/products", GetProducts)
	router.GET("/products/:id", GetProduct)
	router.POST("/products", CreateProduct)
	router.PUT("/products/:id", UpdateProduct)
	router.DELETE("/products/:id", DeleteProduct)

	// 启动服务器
	if err := router.Run(":8080"); err != nil {
		log.Fatal(err)
	}
}

3. 实现 CRUD 操作

现在我们为每个 CRUD 操作定义对应的处理函数。

获取所有产品 (GetProducts)
func GetProducts(c *gin.Context) {
	var products []Product
	if result := db.Find(&products); result.Error != nil {
		c.JSON(500, gin.H{"error": "无法获取产品列表"})
		return
	}
	c.JSON(200, products)
}
根据 ID 获取单个产品 (GetProduct)
func GetProduct(c *gin.Context) {
	id := c.Param("id")
	var product Product
	if result := db.First(&product, id); result.Error != nil {
		c.JSON(404, gin.H{"error": "产品未找到"})
		return
	}
	c.JSON(200, product)
}
创建新产品 (CreateProduct)
func CreateProduct(c *gin.Context) {
	var input Product
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}
	if result := db.Create(&input); result.Error != nil {
		c.JSON(500, gin.H{"error": "创建产品失败"})
		return
	}
	c.JSON(201, input)
}
更新现有产品 (UpdateProduct)
func UpdateProduct(c *gin.Context) {
	id := c.Param("id")
	var product Product
	if result := db.First(&product, id); result.Error != nil {
		c.JSON(404, gin.H{"error": "产品未找到"})
		return
	}

	var input Product
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	product.Code = input.Code
	product.Price = input.Price

	db.Save(&product)
	c.JSON(200, product)
}
删除产品 (DeleteProduct)
func DeleteProduct(c *gin.Context) {
	id := c.Param("id")
	var product Product
	if result := db.First(&product, id); result.Error != nil {
		c.JSON(404, gin.H{"error": "产品未找到"})
		return
	}

	if result := db.Delete(&product); result.Error != nil {
		c.JSON(500, gin.H{"error": "删除产品失败"})
		return
	}

	c.JSON(204, gin.H{"message": "产品已成功删除"})
}

4. 测试 API

启动应用程序后,你可以使用工具如 Postman 或 curl 来测试定义的 API 端点。例如:

  • GET /products:获取所有产品的列表。
  • GET /products/:id:根据 ID 获取单个产品。
  • POST /products:创建新产品,需附带 JSON 数据,如 { "code": "D42", "price": 100 }
  • PUT /products/:id:更新现有产品,需附带 JSON 数据,如 { "code": "D42", "price": 200 }
  • DELETE /products/:id:删除指定 ID 的产品。

总结

通过上述步骤,你已经实现了在 Gin 框架中使用 GORM 对 MySQL 数据库进行基本的 CRUD 操作。这个基础设置可以帮助你快速开始构建基于 RESTful API 的 Web 应用程序。

Gin GORM 查询语句详解

在 Gin 框架中使用 GORM 进行 MySQL 数据库查询时,GORM 提供了多种方法来构建和执行查询语句。这些方法既强大又灵活,能够满足从简单到复杂的各种查询需求。下面我将详细介绍一些常用的 GORM 查询方法,并给出具体的例子。

1. 基本查询

获取所有记录
var products []Product
db.Find(&products) // 获取所有产品记录
根据主键获取单条记录
var product Product
db.First(&product, 1) // 根据主键 ID = 1 获取第一条记录
根据条件获取单条记录
db.Where("code = ?", "D42").First(&product) // 根据条件 code = 'D42' 获取第一条记录

2. 条件查询

你可以通过 Where 方法添加查询条件,支持多种类型的条件表达式。

等值查询
db.Where("price > ?", 100).Find(&products) // 查找价格大于 100 的产品
多个条件
db.Where("code = ? AND price > ?", "D42", 100).Find(&products)
使用结构体或 map 作为条件
// 使用结构体
db.Where(&Product{Code: "D42", Price: 100}).Find(&products)

// 使用 map
db.Where(map[string]interface{}{"code": "D42", "price": 100}).Find(&products)
IN 查询
db.Where("code IN ?", []string{"D42", "L42"}).Find(&products)
LIKE 查询
db.Where("name LIKE ?", "%Apple%").Find(&products)

3. 排序与分页

排序
db.Order("price desc").Find(&products) // 按价格降序排列
分页
page := 1
pageSize := 10
db.Offset((page - 1) * pageSize).Limit(pageSize).Find(&products)

4. 聚合查询

计数
var count int64
db.Model(&Product{}).Count(&count) // 统计产品总数
求和
var sum float64
db.Model(&Product{}).Select("sum(price)").Scan(&sum) // 求所有产品的价格总和

5. 关联查询

假设有一个 Order 模型,它关联了多个 Product

type Order struct {
  gorm.Model
  Products []Product `gorm:"many2many:order_products;"`
}
预加载关联数据
var order Order
db.Preload("Products").First(&order, 1) // 加载订单及其相关的产品

6. 自定义 SQL 查询

如果你需要更复杂的查询,可以直接使用原生 SQL:

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

7. 事务处理

对于需要保证原子性的操作,可以使用事务:

tx := db.Begin()
defer func() {
  if r := recover(); r != nil {
    tx.Rollback()
  }
}()

if err := tx.Error; err != nil {
  return err
}

// 在事务中执行一系列数据库操作
if tx.Where("code = ?", "D42").Delete(&Product{}).Error != nil {
  tx.Rollback()
  return err
}

if tx.Create(&Product{Code: "D42", Price: 100}).Error != nil {
  tx.Rollback()
  return err
}

tx.Commit()

8. 使用回调函数

GORM 支持钩子(callbacks),可以在创建、更新或删除记录前后执行自定义逻辑:

type Product struct {
  gorm.Model
  Code  string
  Price uint
}

func (p *Product) BeforeCreate(tx *gorm.DB) (err error) {
  p.Code = strings.ToUpper(p.Code) // 将代码转换为大写
  return
}

总结

以上就是一些常见的 GORM 查询语句及用法示例。GORM 提供了一套非常直观且强大的 API 来进行数据库查询,使得开发者可以专注于业务逻辑而不需要编写大量的 SQL 语句。当然,GORM 的功能远不止于此,还有许多高级特性等待你去探索。

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

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

相关文章

Redis的内存预分配策略

Redis的内存预分配策略是一种优化手段,旨在减少频繁的内存分配和释放操作对性能的影响。以下是对Redis在使用各数据结构类型时内存变化以及触发底层数据结构变化条件的详细分析: 一、内存预分配策略概述 Redis通过预先分配足够的内存,可以提高…

卸载wps后word图标没有变成白纸恢复

这几天下载了个wps教育版,后头用完了删了 用习惯的2019图标 给兄弟我干没了??? 其他老哥说什么卸载关联重新下 ,而且还要什么撤销保存原来的备份什么,兄弟也是不得不怂了 后头就发现了这个半宝藏博主&…

麒麟服务器安装kafka--亲测

我这安装的是单机版本的: 下载地址:Index of /kafka/3.9.0 我下载的是:https://dlcdn.apache.org/zookeeper/zookeeper-3.9.3/apache-zookeeper-3.9.3-bin.tar.gz https://dlcdn.apache.org/kafka/3.9.0/kafka_2.12-3.9.0.tgz 一、下载并上…

104周六复盘 (188)UI

1、早上继续看二手书的一个章节,程序开发流程、引擎、AI等内容, 内容很浅,基本上没啥用,算是复习。 最大感触就是N年前看同类书的里程碑、AI相关章节时,会感觉跟自己没啥关系, 而如今则密切相关&#xf…

Chromebook 的 4 个最佳变声器

您对使用chromebook 变声器感到困惑吗?您是否认为在 Chromebook 上安装变声器很困难?如果是,那么这篇文章适合您,因为在 Chromebook 上安装和使用简单且准确的变声器非常简单且轻松。 在本文中,我们将分享适用于 Chro…

DC系列之DC-8渗透测试

DC-8 靶机渗透测试实战 靶机下载地址: https://download.vulnhub.com/dc/DC-8.zip(下载速度慢可以用迅雷下载) 一、实验环境 实验环境: kali2024:192.168.234.145(nat模式) 靶机环境DC-7&#…

12306分流抢票软件 bypass v1.16.43 绿色版(春节自动抢票工具)

软件介绍 12306Bypass分流抢票软件,易操作强大的12306抢票软件,全程自动抢票,云识别验证码打码,多线程秒单、稳定捡漏,支持抢候补票、抢到票自动付款,支持多天、多车次、多席别、多乘客、短信提醒等功能。…

NS4861 单灯指示独立耳锂电池充放电管理 IC

1 特性  最大 500mA 线性充电电流,外部可调节  内部预设 4.2V 充电浮充电压  支持 0V 电池充电激活  支持充满 / 再充功能  内置同步升压放电模块,输出电压 5.1V  同步升压 VOUT 最大输出电流 500mA  VOL/OR 独…

基于Java的敬老院管理系统的设计和实现【源码+文档+部署讲解】

基于Java的敬老院管理系统设计和实现 摘 要 新世纪以来,互联网与计算机技术的快速发展,我国也迈进网络化、集成化的信息大数据时代。对于大众而言,单机应用早已成为过去,传统模式早已满足不了当下办公生活等多种领域的需求,在一台电脑上不联网的软件少之又少&#x…

基于YOLOv8的道路缺陷检测系统

基于YOLOv8的道路缺陷检测系统 (价格80) 包含 [Block crack, Longitudinal crack, Strip repair, Transverse crack] [‘块状裂缝’,‘纵向裂缝’,‘修复’,‘横向裂缝’] 4个类 通过PYQT构建UI界面,包含图片检测&#xff…

我用AI学Android Jetpack Compose之开篇

最近突发奇想,想学一下Jetpack Compose,打算用Ai学,学最新的技术应该要到官网学,不过Compose已经出来一段时间了,Ai肯定学过了,用Ai来学,应该问题不大,学习过程记录下来,…

unity学习7:unity的3D项目的基本操作: 坐标系

目录 学习参考 1 unity的坐标系 1.1 左手坐标系 1.2 左手坐标系和右手坐标系的区别 1.3 坐标系的原点(0,0,0) 2 坐标系下的具体xyz坐标 2.1 position这里的具体xyz坐标值 2.2 父坐标 2.3 世界坐标和相对坐标 2.3.1 世界坐标 2.3.2 相对坐标 2.4 父物体,…

爬虫案例-爬取某度文档

文章目录 1、第三方库的安装和pytesseract安装2、爬取某度文档的代码3、效果图 1、第三方库的安装和pytesseract安装 #以下是安装http请求的第三方库 pip install requests #以下是安装处理文档的第三方库 pip install python-docx #以下是安装处理图片的第三方库 pip install…

在Lua中,Metatable元表如何操作?

Lua中的Metatable(元表)是一个强大的特性,它允许我们改变表(table)的行为。下面是对Lua中的Metatable元表的详细介绍,包括语法规则和示例。 1.Metatable介绍 Metatable是一个普通的Lua表,它用于…

【Ubuntu20.04】Apollo10.0 Docker容器部署+常见错误解决

官方参考文档【点击我】 Apollo 10.0 版本开始,支持本机和Docker容器两种部署方式。 如果您使用本机部署方式,建议使用x86_64架构的Ubuntu 22.04操作系统或者aarch64架构的Ubuntu 20.04操作系统。 如果您使用Docker容器部署方式,可以使用x…

springboot整合Logback

Logback介绍 描述 Logback是由log4j创始人设计的另外一种开源日志组件,性能比log4j要好。相对是一个可靠、通用、快速而又灵活的Java日志框架。 Logback主要分三个模块 1、logback-core:其他两个模块的基础模块 2、logback-classic:它是lo…

仓库叉车高科技安全辅助设备——AI防碰撞系统N2024G-2

在当今这个高效运作、安全第一的物流时代,仓库作为供应链的中心地带,其安全与效率直接关系到企业的命脉。 随着科技的飞速发展,传统叉车作业模式正逐步向智能化、安全化转型,而在这场技术革新中,AI防碰撞系统N2024G-2…

学习笔记|arduino uno r3| RGB 灯珠|Atmega328P|PWM|analogWrite|analogRead函数: RGB灯珠呼吸灯

目录 RGB 灯珠呼吸灯实验RGB 灯珠实验概述工作原理组件清单接线程序代码编译和执行 Tips: Arduino常用的函数解释analogWrite(pin, value)函数analogRead(pin)函数 总结 RGB 灯珠呼吸灯实验 RGB 灯珠实验概述 1-三色LED黑板模块的PCB颜色为黑色,使用5M…

杰发科技——使用ATCLinkTool解除读保护

0. 原因 在jlink供电电压不稳定的情况下,概率性出现读保护问题,量产时候可以通过离线烧录工具避免。代码中开了读保护,但是没有通过can/uart/lin/gpio控制等方式进行关闭,导致无法关闭读保护。杰发所有芯片都可以用本方式解除读保…

ICLR2017 | I-FGSM | 物理世界中的对抗样本

Adversarial Examples in The Physical World 摘要-Abstract引言-Introduction生成对抗图像的方法-Methods of Generating Adversarial Images对抗样本的图片-Photos of Adversarial Examples对抗图像的破坏率-Destruction Rate of Adversarial Images实验设置-Experimental Se…