Go语言Gin框架中使用MySQL数据库的三种方式

news2024/11/25 21:26:17

文章目录

  • 原生SQL操作
  • XORM
  • GORM

本文演示在Gin框架中通过三种方式实现增删改查的操作,数据表结构如下:

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `user_no` bigint(20) unsigned NOT NULL COMMENT '用户编号',
  `name` varchar(255) NOT NULL DEFAULT '' COMMENT '用户姓名',
  `age` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '用户年龄',
  `address` varchar(255) NOT NULL DEFAULT '' COMMENT '地址',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间',
  `update_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `key_user_no` (`user_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

原生SQL操作

在Gin框架中使用MySQL的最简单的方式就是直接处理SQL语句,记得引入 _ "github.com/go-sql-driver/mysql"

代码如下:

//公共方法封装
package dbUtil

import (
	"database/sql"
	"fmt"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"net/http"
	"strconv"
)

var tableName = "users" //数据表名
var result ResponseData //响应结果数据

// 统一返回数据的结构体
type ResponseData struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

func showSuccess(c *gin.Context, data interface{}) {
	result.Code = http.StatusOK
	result.Message = "操作成功"
	result.Data = data
	c.JSON(http.StatusOK, result)
	return
}

func showError(c *gin.Context, message string) {
	result.Code = http.StatusBadRequest
	result.Message = message
	result.Data = nil
	c.JSON(http.StatusOK, result)
	return
}

// 使用原生SQL语句
// go-sql-driver地址:https://github.com/go-sql-driver/mysql
var sqlDb *sql.DB //数据库连接db

// 初始化
func init() {
	//打开数据库
	//parseTime:时间格式转换(查询结果为时间时,是否自动解析为时间);
	//loc=Local:MySQL的时区设置
	sqlStr := "root:rx123456@tcp(127.0.0.1:3306)/gin_demo?charset=utf8&parseTime=true&loc=Local"
	var err error
	sqlDb, err = sql.Open("mysql", sqlStr)
	if err != nil {
		fmt.Println("数据库打开失败:", err)
		return
	}

	//测试与数据库建立的连接,非必要(校验连接是否正确)
	err = sqlDb.Ping()
	if err != nil {
		fmt.Println("数据库连接失败:", err)
		return
	}
}

// 用户结构体
type sqlUserData struct {
	Id      int    `json:"id"`
	UserNo  int    `json:"user_no"`
	Name    string `json:"name"`
	Age     int    `json:"age"`
	Address string `json:"address"`
	Remarks string `json:"remarks"`
}

func MysqlInsertData(c *gin.Context) {
	/*
		//请求参数
		{
			"user_no":1001,
			"name":"张三",
			"age":18,
			"address":"北京昌平"
		}
	*/
	var user sqlUserData
	err := c.Bind(&user)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	sqlStr := "insert into " + tableName + "(user_no, name, age, address) values (?,?,?,?)"
	ret, err := sqlDb.Exec(sqlStr, user.UserNo, user.Name, user.Age, user.Address)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		showError(c, fmt.Sprint(err))
		return
	}
	newDataId, _ := ret.LastInsertId()
	showSuccess(c, "新增的结果id:"+strconv.Itoa(int(newDataId)))
}

在这里插入图片描述

func MysqlGetUserList(c *gin.Context) {
	name := c.Query("name")
	sqlStr := "select id,user_no,name,age,address from " + tableName + " where name=?"
	rows, err := sqlDb.Query(sqlStr, name)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	defer rows.Close()
	userList := make([]sqlUserData, 0)
	for rows.Next() {
		var user sqlUserData
		rows.Scan(&user.Id, &user.UserNo, &user.Name, &user.Age, &user.Address)
		if user.Age >= 18 {
			user.Remarks = "已成年"
		} else {
			user.Remarks = "未成年"
		}
		userList = append(userList, user)
	}
	showSuccess(c, userList)
}

在这里插入图片描述

func MysqlGetUserInfo(c *gin.Context) {
	id := c.Query("id")
	sqlStr := "select id,user_no,name,age,address from " + tableName + " where id=?"
	var user sqlUserData
	err := sqlDb.QueryRow(sqlStr, id).Scan(&user.Id, &user.UserNo, &user.Name, &user.Age, &user.Address)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	showSuccess(c, user)
}

在这里插入图片描述

func MysqlUpdateData(c *gin.Context) {
	/*
		//请求参数
		{
		    "id":1,
		    "age":13,
		    "address":"河北"
		}
	*/
	var user sqlUserData
	err := c.Bind(&user)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	sqlStr := "update " + tableName + " set age=? ,address=? where id=?"
	ret, err := sqlDb.Exec(sqlStr, user.Age, user.Address, user.Id)
	if err != nil {
		fmt.Printf("update failed, err:%v\n", err)
		showError(c, fmt.Sprint(err))
		return
	}
	res, _ := ret.RowsAffected()
	showSuccess(c, "受影响的行数:"+strconv.Itoa(int(res)))
}

在这里插入图片描述

func MysqlDeleteData(c *gin.Context) {
	id := c.Query("id")
	var count int
	//先查询
	sqlStr := "select count(*) from " + tableName + " where id=?"
	err := sqlDb.QueryRow(sqlStr, id).Scan(&count)
	if count <= 0 || err != nil {
		showError(c, "数据不存在")
		return
	}

	//再删除
	delStr := "delete from " + tableName + " where id=?"
	ret, err := sqlDb.Exec(delStr, id)
	if err != nil {
		fmt.Printf("delete failed, err:%v\n", err)
		showError(c, fmt.Sprint(err))
		return
	}
	res, _ := ret.RowsAffected()
	showSuccess(c, "受影响的行数:"+strconv.Itoa(int(res)))
}

在这里插入图片描述

XORM

xorm是一个Go语言的ORM库,通过它可以很方便的操作数据库。它的设计重点是高性能和易用性。XORM支持多种数据库,包括MySQL、PostgreSQL、SQLite、Oracle和SQL Server,并提供了丰富的查询语言。XORM还支持事务和缓存机制,可以提高数据库操作的性能。添加依赖:go get github.com/go-xorm/xorm

ORM,即pobject-RelationlMapping,它的作用是在关系型数据库和对象之间作一个映射,这样我们在具体操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。
比较好的Go语言ORM包括:xorm与gorm

下面是代码实现:

package dbUtil

import (
	"fmt"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"
	"strconv"
	"time"
)

var myXorm *xorm.Engine

// 定义结构体(xorm支持双向映射);如果表不存在,则会自动创建
type users struct {
	Id         int64     `xorm:"pk autoincr" json:"id"` //指定主键并自增
	UserNo     int       `xorm:"unique" json:"user_no"`
	Name       string    `json:"name"`
	Age        int       `json:"age"`
	Address    string    `json:"address"`
	CreateTime time.Time `xorm:"created" json:"create_time"`
	UpdateTime time.Time `xorm:"updated" json:"update_time"`
}

func init() {
	sqlStr := "root:rx123456@tcp(127.0.0.1:3306)/gin_demo?charset=utf8&parseTime=true&loc=Local"
	var err error

	//创建数据库引擎
	myXorm, err = xorm.NewEngine("mysql", sqlStr)
	if err != nil {
		fmt.Println("数据库连接失败:", err)
	}

	//创建或者同步表,表名称是users
	//如果数据表不存在,会根据users结构体自动创建
	err = myXorm.Sync(new(users))
	if err != nil {
		fmt.Println("数据表同步失败:", err)
	}
}

func XormGetUserList(c *gin.Context) {
	name := c.Query("name")
	var user []users
	err := myXorm.Where("name=?", name).And("age>20").Limit(10, 0).Asc("age").Find(&user)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	showSuccess(c, user)
}

func XormGetUserInfo(c *gin.Context) {
	id := c.Query("id")
	var user []users
	err := myXorm.Where("id=?", id).Find(&user)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	if len(user) == 0 {
		showSuccess(c, nil)
	}
	showSuccess(c, user[0])
}

func XormInsertData(c *gin.Context) {
	/*
		//请求参数
		{
			"user_no":1001,
			"name":"张三",
			"age":18,
			"address":"北京昌平"
		}
	*/
	var user users
	err := c.Bind(&user)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	affected, err := myXorm.Insert(user)
	if err != nil || affected <= 0 {
		fmt.Printf("insert failed, err:%v\n", err)
		showError(c, fmt.Sprint(err))
		return
	}
	showSuccess(c, "受影响的行数:"+strconv.Itoa(int(affected)))
}

func XormUpdateData(c *gin.Context) {
	/*
		//请求参数
		{
		    "id":1,
		    "age":13,
		    "address":"河北"
		}
	*/
	var u users
	err := c.Bind(&u)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}

	//先查找
	var user []users
	err = myXorm.Where("id=?", u.Id).Find(&user)
	//fmt.Println(myXorm.NewSession().LastSQL())
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	if len(user) == 0 {
		showError(c, "数据不存在")
		return
	}

	//再修改
	affected, err := myXorm.Where("id=?", u.Id).Update(&users{
		Age:     u.Age,
		Address: u.Address,
	})
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	showSuccess(c, "受影响的行数:"+strconv.Itoa(int(affected)))
}

func XormDeleteData(c *gin.Context) {
	id := c.Query("id")
	//先查找
	var user []users
	err := myXorm.Where("id=?", id).Find(&user)
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	if len(user) == 0 {
		showError(c, "数据不存在")
		return
	}

	//再删除
	affected, err := myXorm.Where("id=?", id).Delete(&users{})
	if err != nil {
		showError(c, fmt.Sprint(err))
		return
	}
	showSuccess(c, "受影响的行数:"+strconv.Itoa(int(affected)))
}

GORM

GORM是Go语言中最受欢迎的ORM框架之一。它具有易于使用的API和灵活的查询语言,支持多种类型的数据库,包括MySQL、PostgreSQL、SQLite和SQL Server。GORM还提供了自动迁移功能,可以在应用程序启动时自动创建数据库表和字段。
使用方法:添加依赖 go get gorm.io/gormgo get gorm.io/driver/mysql

实现代码如下:

package dbUtil

import (
	"fmt"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"time"
)

var gormDB *gorm.DB

// 定义结构体
// 特别注意:结构体名称为:user,创建的表的名称为:users
type user struct {
	Id         int       `gorm:"primaryKey;autoIncrement" json:"id"` //指定主键并自增
	UserNo     int       `gorm:"unique" json:"user_no"`
	Name       string    `gorm:"type:varchar(256);not null" json:"name"`
	Age        int       `gorm:"type:tinyint(4);not null" json:"age"`
	Address    string    `gorm:"type:varchar(256);not null" json:"address"`
	CreateTime time.Time `json:"create_time"`
	UpdateTime time.Time `json:"update_time"`
}

func init() {
	var err error
	sqlStr := "root:rx123456@tcp(127.0.0.1:3306)/gin_demo?charset=utf8mb4&parseTime=true&loc=Local"
	gormDB, err = gorm.Open(mysql.Open(sqlStr), &gorm.Config{}) //配置项中预设了连接池 ConnPool
	if err != nil {
		fmt.Println("数据库连接出错:", err)
		return
	}
}

// 捕获异常
func catchException(c *gin.Context) {
	err := recover()
	if err != nil {
		showError(c, fmt.Sprint(err))
	}
}

func GormGetUserList(c *gin.Context) {
	defer func() {
		catchException(c)
	}()

	name := c.Query("name")
	myUser := make([]user, 10)
	tx := gormDB.Where("name=?", name).Find(&myUser).Limit(10) //查询到的有可能为多行,所以采用结构体切片
	if tx.Error != nil {
		showError(c, fmt.Sprint(tx.Error))
		return
	}
	showSuccess(c, myUser)
}

func GormGetUserInfo(c *gin.Context) {
	defer func() {
		catchException(c)
	}()

	id := c.Query("id")
	myUser := user{}
	tx := gormDB.Where("id=?", id).First(&myUser)
	if tx.Error != nil {
		showError(c, fmt.Sprint(tx.Error))
		return
	}
	showSuccess(c, myUser)
}

func GormInsertData(c *gin.Context) {
	/*
		//请求参数
		{
			"user_no":1001,
			"name":"张三",
			"age":18,
			"address":"北京昌平"
		}
	*/

	defer func() {
		catchException(c)
	}()

	var myUser user
	err := c.Bind(&myUser)
	if err != nil {
		showError(c, fmt.Sprint(err))
	}
	fmt.Println("myUser", myUser)
	tx := gormDB.Create(&myUser)
	fmt.Println(tx)
	if tx.RowsAffected > 0 {
		showSuccess(c, tx.RowsAffected)
		return
	} else {
		fmt.Printf("insert failed, err:%v\n", err)
		showError(c, fmt.Sprint(tx.Error))
	}
}

func GormUpdateData(c *gin.Context) {
	/*
		//请求参数
		{
		    "id":1,
		    "age":13,
		    "address":"河北"
		}
	*/
	defer func() {
		catchException(c)
	}()

	var myUser user
	err := c.Bind(&myUser)
	if err != nil {
		showError(c, fmt.Sprint(err))
	}
	fmt.Println("myUser", myUser)

	//先查找
	var count int64
	gormDB.Model(&user{}).Where("id=?", myUser.Id).Count(&count)
	if count == 0 {
		showError(c, "数据不存在")
		return
	}
	//再更新
	tx := gormDB.Model(&user{}).Where("id=?", myUser.Id).Updates(&myUser)
	fmt.Println(tx) //打印结果
	if tx.RowsAffected > 0 {
		showSuccess(c, tx.RowsAffected)
	} else {
		showError(c, fmt.Sprint(tx.Error))
	}
}

func GormDeleteData(c *gin.Context) {
	defer func() {
		catchException(c)
	}()

	id := c.Query("id")
	//先查找
	var count int64
	gormDB.Model(&user{}).Where("id=?", id).Count(&count)
	if count == 0 {
		showError(c, "数据不存在")
		return
	}
	//再删除
	tx := gormDB.Where("id=?", id).Delete(&user{})
	fmt.Println(tx) //打印结果
	if tx.RowsAffected > 0 {
		showSuccess(c, tx.RowsAffected)
	} else {
		showError(c, fmt.Sprint(tx.Error))
	}
}

GORM和XORM都是优秀的ORM框架,它们之间的一些区别:

  • 查询语言:GORM使用链式查询语法,而XORM使用结构体作为查询条件。XORM的查询语言更为灵活,可以支持更复杂的查询。
  • 性能:XORM的性能比GORM更高,在大量数据的情况下,XORM能够更快地进行数据库操作。
  • 易用性:GORM的API比XORM更易用,特别是对于没有ORM经验的开发者来说。
  • 社区支持:GORM的社区比XORM更大,因此有更多的文档、示例和插件可以使用。

源代码:https://gitee.com/rxbook/gin-demo/tree/master/dbUtil

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

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

相关文章

Ansible --- playbook 剧本

一、playbook 的简介 playbook是 一个不同于使用Ansible命令行执行方式的模式&#xff0c;其功能更强大灵活。 简单来说&#xff0c;playbook是一个非常简单的配置管理和多主机部署系统&#xff0c; 不同于任何已经存在的模式&#xff0c;可作为一个适合部署复杂应用程序的基…

win11 定时计划任务

控制面板 任务计划 添加任务计划 &#xff0c;选按步骤添加。

2023年【天津市安全员C证】模拟考试及天津市安全员C证实操考试视频

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 天津市安全员C证模拟考试是安全生产模拟考试一点通生成的&#xff0c;天津市安全员C证证模拟考试题库是根据天津市安全员C证最新版教材汇编出天津市安全员C证仿真模拟考试。2023年【天津市安全员C证】模拟考试及天津市…

docker全家桶(基本命令、dockerhub、docker-compose)

概念 应用场景&#xff1a; Web 应用的自动化打包和发布。自动化测试和持续集成、发布。在服务型环境中部署和调整数据库或其他的后台应用。从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。 作用&#xff1a;Docker 使您能够将应用程序与基…

算法通关村第19关【青铜】| 动态规划

动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种解决多阶段决策过程最优化问题的数学方法。它通常用于解决那些具有重叠子问题和最优子结构性质的问题&#xff0c;这些问题可以分解为多个相互关联的子问题。 动态规划的核心思想是将原问题分解为…

Android查看签名信息系列 · 使用逆向分析工具JadxGUI获取签名

前言 Android查看签名信息系列之使用逆向分析工具JadxGUI获取签名&#xff0c;通过这种方式&#xff0c;可以获取到的签名信息包括&#xff1a;MD5、SHA1、SHA-256、公钥(模数)等信息 实现方法 1、进入JadxGUI目录下的lib文件夹内&#xff0c;找到jadx-gui-1.4.7.jar文件 2、…

医疗制药行业数字化创新实践

本文将为大家分享3个制药行业的创新案例吧&#xff0c;都是在不同智能制造落地场景下的典型案例&#xff0c;希望对大家有所启发。 01 医疗设备企业零代码搭建集成式信息化管理平台&#xff0c;年节省150余万元 医疗制药行业数字化实现工具>>>>https://www.jianda…

LLVM(6)ORC实例分析:Transform in cpp

Transform用例总结 该用例调用JIT的setTransform接口&#xff0c;传入pass对IR代码做了一系列优化。优化一&#xff1a;fac函数的调用者能直接拿到返回值&#xff0c;不在需要进入fac计算了。 正常函数调用a fac(5)需要进入fac函数后才能拿到结果120。transform后&#xff0c…

java部署教程

关闭防火墙 不管是windows还是linux&#xff0c;首先必须关闭防火墙。 # linux添加8080端口 firewall-cmd --zonepublic --add-port8080/tcp --permanent#删除80端口 firewall-cmd --zonepublic --remove-port8080/tcp --permanent# 刷新使端口立即生效 firewall-cmd --reloa…

AI大模型下一步怎么走?百度携AI原生应用抢先作答

前言 10月17日&#xff0c;百度世界2023在北京首钢园召开&#xff0c;这是百度近四年来首次恢复线下举办世界大会&#xff0c;会上发布了文心大模型4.0以及基于大模型的AI原生应用的最新进展。 文章目录 前言我眼里的百度世界大会文心大模型4.0正式发布&#xff0c;与GPT4相比毫…

解决spring项目中无法加载resources下文件

解决spring项目中无法加载resources下文件 问题发现问题解决步骤一&#xff1a;检查文件名步骤二&#xff1a;确保测试资源目录步骤三&#xff1a;检查文件路径是否正确 问题发现 在学习Spring过程中&#xff0c;TestContext框架试图检测一个默认的XML资源位置。如果您的类被命…

数字孪生的多领域应用:塑造未来的可能性

数字孪生技术正迅速改变着我们与世界互动的方式&#xff0c;为各个领域带来了前所未有的机会。从制造业到医疗保健&#xff0c;再到城市规划和交通系统&#xff0c;数字孪生正在成为创新和效率提升的引擎。本文带大家分析数字孪生的一些应用场景和其潜在影响的更多细节&#xf…

QT中使用QVTKOpenGLNativeWidget的简单教程以及案例

先添加一个带有ui的QT应用程序。 一、在ui界面中添加QVTKOpenGLNativeWidget控件 先拖出来一个QOpenGLWidget控件 修改布局如下&#xff1a; 然后将QOpenGLWidget控件提升为QVTKOpenGLNativeWidget控件&#xff0c;步骤如下&#xff1a; 右击QOpenGLWidget窗口&#xff0c;选…

知识蒸馏(Knowledge Distillation)简述

知识蒸馏&#xff08;Knowledge Distillation&#xff09;简述 结论 Reference&#xff1a; Distilling the Knowledge in a Neural Network知识蒸馏&#xff08;Knowledge Distillation&#xff09;简述&#xff08;一&#xff09; 知识蒸馏被广泛用于模型压缩和迁移学习当中…

【STM32】--基础了解

一、STM32来历背景 1.从51到STM32 &#xff08;1&#xff09;单片机有很多种 &#xff08;2&#xff09;STM32内核使用ARM&#xff0c;但是ARM不一定是STM32 &#xff08;3&#xff09;ATM32是当前主流的32位高性能单片机 &#xff08;4&#xff09;STM32的特点&#xff1a;高…

数据发现工具

数据发现是从非结构化和结构化数据源中查找特定数据子集的过程&#xff0c;必须查明业务存储库中有哪些数据以及位置&#xff0c;数据发现与数据分类&#xff0c;这是根据其敏感性和脆弱性对不同类型的数据进行排序的过程&#xff0c;敏感数据发现和分类本身就是不同的过程&…

测试网线的仪器叫什么?

测试网线的仪器有哪些&#xff1f;测试网线的仪器叫什么&#xff1f;很多小伙伴对此有疑问。咱们逐一分析&#xff0c;并做出简单的讨论。 测试网线的仪器大概几类&#xff0c;从携带是否方便上来说&#xff0c;手持式和台式。从测试功能上来说&#xff0c;分为物理常量、电气…

利用在线培训系统提升员工技能,助力企业发展

近年来&#xff0c;随着互联网技术的发展&#xff0c;在线培训系统逐渐成为企业提升员工技能的利器。这种新型的培训方式打破了时间和空间的限制&#xff0c;为企业提供了更加灵活和高效的培训解决方案。下面&#xff0c;我们将详细介绍如何利用在线培训系统提升员工技能&#…

驱动数字化转型,Doris Summit Asia 2023 智慧金融与政企论坛精彩预告!

峰会官网已上线&#xff0c;最新议程请关注&#xff1a;doris-summit.org.cn 即刻报名 Doris Summit 是 Apache Doris 社区一年一度的技术盛会&#xff0c;由飞轮科技联合 Apache Doris 社区的众多开发者、企业用户和合作伙伴共同发起&#xff0c;专注于传播推广开源 OLAP 与…

一图看懂CodeArts Governance 三大特性,带你玩转开源治理服务

华为云开源治理服务CodeArts Governance是针对软件研发提供的一站式开源软件治理服务&#xff0c;凝聚华为在开源治理上的优秀实践经验&#xff0c;提供开源软件元数据及软件成分分析、恶意代码检测等能力&#xff0c;从合法合规、网络安全、供应安全等维度消减开源软件使用风险…