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

GinVueAdmin源码分析3-整合MySQL

目录

      • 文件结构
      • 数据库准备
      • 配置文件处理
        • config.go
        • db_list.go
        • gorm_mysql.go
        • system.go
      • 初始化数据库
        • gorm.go
        • gorm_mysql.go
        • 开始初始化
      • 测试数据库
        • 定义实体类 User
        • service
        • api
        • 开始测试!

文件结构

本文章将使用到上一节创建的 CommonService 接口,用于测试连接数据库状况,当然您也可以自制简单接口作为测试,不会影响整体工作流程!

下方树状图为最终项目结构

文件夹 api 与 service 助力数据库查询请求

initialize/gorm.go 初始化 GORM
initialize/gorm_mysql.go 执行 MySQL 数据库对应的初始化过程

user.go 一个实体类

│  config.yaml
│  go.mod
│  go.sum
│  main.go
│
├─api
│  │  enter.go
│  │
│  ├─example
│  └─system
│          api_common.go
│          enter.go
│
├─config
│      config.go
│      db_list.go
│      gorm_mysql.go
│      jwt.go
│      local.go
│      system.go
│
├─core
│      constant.go
│      server.go
│      viper.go
│
├─global
│      global.go
│
├─initialize
│  │  gorm.go
│  │  gorm_mysql.go
│  │  router.go
│  │
│  └─internal
│          gorm.go
│
├─model
│      user.go
│
├─router
│  │  enter.go
│  │
│  ├─example
│  └─system
│          enter.go
│          sys_common.go
│
└─service

之后回到项目根目录,打开命令行,输入指令安装 MySQL 驱动:
go get -u gorm.io/driver/mysql


数据库准备

这是我本地使用的数据库参数:
username:root
password:123456
dbname:golang

这是数据库“golang”中的数据表 user 的数据,注意到有四个属性

在这里插入图片描述


来到 go 项目中,根据上述参数,打开 config.yaml,添加 mysql 配置
(这里为了便于大家操作,省去了源码中的注册 zap 的部分)

同时添加 system 对象,内含一个 db-type 属性,用来定义我们希望后端链接的数据库类型

system:db-type: "mysql"mysql:path: "localhost"port: "3306"config: ""db-name: "golang"username: "root"password: "123456"max-idle-conns: 10max-open-conns: 100

配置文件处理

由于我们为 config.yaml 添加了新的配置项,所以需要按照我们之前文章所属,为其配置指定的结构!


config.go

打开(如果你跟随上上节文章)或者新建文件 config/config.go

在主 config 入口添加 mysql 属性

type Server struct {...Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
}

db_list.go

新建文件 config/db_list.go

由于我们有可能需要支持多种类型的数据库(比如 PostgreSQL),所以最佳解决办法就是创建一个通用的数据库参数结构体

DSNProvider 接口用来给 GORM 提供 DSN

type DSNProvider interface {Dsn() string
}type GeneralDB struct {Path         string `mapstructure:"path" json:"path" yaml:"path"`                               // 服务器地址:端口Port         string `mapstructure:"port" json:"port" yaml:"port"`                               //:端口Config       string `mapstructure:"config" json:"config" yaml:"config"`                         // 高级配置Dbname       string `mapstructure:"db-name" json:"db-name" yaml:"db-name"`                      // 数据库名Username     string `mapstructure:"username" json:"username" yaml:"username"`                   // 数据库用户名Password     string `mapstructure:"password" json:"password" yaml:"password"`                   // 数据库密码Prefix       string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`                         //全局表前缀,单独定义TableName则不生效Singular     bool   `mapstructure:"singular" json:"singular" yaml:"singular"`                   //是否开启全局禁用复数,true表示开启Engine       string `mapstructure:"engine" json:"engine" yaml:"engine" default:"InnoDB"`        //数据库引擎,默认InnoDBMaxIdleConns int    `mapstructure:"max-idle-conns" json:"max-idle-conns" yaml:"max-idle-conns"` // 空闲中的最大连接数MaxOpenConns int    `mapstructure:"max-open-conns" json:"max-open-conns" yaml:"max-open-conns"` // 打开到数据库的最大连接数
}

gorm_mysql.go

新建文件 gorm_mysql.go

在这里定义 mysql 结构体,直接使用通用数据库参数结构体 GeneralDB 即可

然后于此实现接口 DSNProvider ,构造 DSN

type Mysql struct {GeneralDB `yaml:",inline" mapstructure:",squash"`
}func (m *Mysql) Dsn() string {return m.Username + ":" + m.Password + "@tcp(" + m.Path + ":" + m.Port + ")/" + m.Dbname + "?" + m.Config
}

system.go

打开文件 config/system.go

老样子,为 db_type 配置对应结构体内容

type System struct {DbType string `mapstructure:"db-type" json:"db-type" yaml:"db-type"`
}

初始化数据库

gorm.go

新建文件 initialize/gorm.go

此处的逻辑很简单,即通过全局变量获取 db_type 属性,得知开发者想要用那种数据库;
由于我们只会用到 MySQL,故这里的判断就都启动 mysql 了

GormMysql 目前处于飘红状态,因为还没有定义,下面我们将为其定义初始化 MySQL 的方法

import ("ginlogin/global""gorm.io/gorm"
)func Gorm() *gorm.DB {switch global.G_CONFIG.System.DbType {case "mysql":return GormMysql()default:return GormMysql()}
}

gorm_mysql.go

新建文件 initialize/gorm_mysql.go

具体通过 GORM 链接 mysql 的过程相信大家也很熟悉,这里就不多费口舌了,直接看注释吧!

import ("fmt""ginlogin/global""gorm.io/driver/mysql""gorm.io/gorm"
)// 初始化mysql方法,返回一个gorm.DB引用
func GormMysql() *gorm.DB {// 第一步// 全局变量获取config中定义的mysql参数// 判断如果不急于数据库名,直接返回nil表示初始化数据库失败info := global.G_CONFIG.Mysqlif info.Dbname == "" {return nil}// 第二步// 构造mysqlConfigmysqlConfig := mysql.Config{DSN:                       info.Dsn(),DefaultStringSize:         191,SkipInitializeWithVersion: false,}// 第三步// gorm.Open连接到数据库,并处理错误if db, err := gorm.Open(mysql.New(mysqlConfig)); err != nil {fmt.Println("完蛋,连接不上数据库!!!")return nil} else {// 如果成功链接,设置好连接池啥的,就可以返回db了db.InstanceSet("gorm:table_options", "ENGINE="+info.Engine)sqlDB, _ := db.DB()sqlDB.SetMaxIdleConns(info.MaxIdleConns)sqlDB.SetMaxOpenConns(info.MaxOpenConns)return db}
}

开始初始化

哎?这还没完,你还要调用初始化方法!

打开 main.go,添加如下代码,调用 GORM 初始化方法

func main() {// 初始化数据库DBglobal.G_DB = initialize.Gorm()...
}

此处关于整合 mysql 的部分已经完结了,下面将是测试数据库的内容,您可以直接略过


测试数据库

定义实体类 User

新建文件 model/user.go

根据开头所述 user 表,故可定义如下实体类

type User struct {Id       int    `json:"id"`Username string `json:"username"`Password string `json:"password"`Role     int    `json:"role"`
}// 显式指定表名
func (User) TableName() string {return "user"
}

service

打开文件 service/system/service_common.go

service 层内简单实现了查询整张表的功能,并作了错误处理

type CommonService struct{}func (s *CommonService) CreateApi(c *gin.Context) (err error) {// 调用Find方法查询表,将查询成功与否的结果存到res变量var userList []model.Userres := global.G_DB.Find(&userList)// 判断res是否出现了错误if errors.Is(res.Error, gorm.ErrRecordNotFound) {return errors.New("找不到这个元素")}// 如果没错,那就返回数据c.JSON(http.StatusOK, gin.H{"data": userList,})// 给api层传递一个errorreturn res.Error
}

api

打开文件 api/system/api_common.go

很简单,调用 service,然后在 api 中处理错误并返回 JSON 数据(这一步也可以直接全部写在 service 层里,此时就可以把该 api 层看做是 springboot 中的 controller 层了!)

import ("github.com/gin-gonic/gin""net/http"
)type CommonApi struct{}func (s *CommonApi) CreateApi(c *gin.Context) {err := commonService.CreateApi(c)if err != nil {c.JSON(http.StatusBadRequest, gin.H{"status": err.Error(),})}
}

开始测试!

万事俱备,只欠东风,打开你的 postman|apifox|apipost,请求以下看看结果吧!


相关文章:

GinVueAdmin源码分析3-整合MySQL

目录文件结构数据库准备配置文件处理config.godb_list.gogorm_mysql.gosystem.go初始化数据库gorm.gogorm_mysql.go开始初始化测试数据库定义实体类 Userserviceapi开始测试!文件结构 本文章将使用到上一节创建的 CommonService 接口,用于测试连接数据库…...

大数据框架之Hadoop:MapReduce(三)MapReduce框架原理——MapReduce开发总结

在编写MapReduce程序时,需要考虑如下几个方面: 1、输入数据接口:InputFormat 默认使用的实现类是:TextInputFormatTextInputFormat的功能逻辑是:一次读一行文本,然后将该行的起始偏移量作为key&#xff0…...

requests---(4)发送post请求完成登录

前段时间写过一个通过cookies完成登录,今天我们写一篇通过post发送请求完成登录豆瓣网 模拟登录 1、首先找到豆瓣网的登录接口 打开豆瓣网站的登录接口,请求错误的账号密码,通过F12或者抓包工具找到登录接口 通过F12抓包获取到请求登录接口…...

Python抓取数据具体流程

之前看了一段有关爬虫的网课深有启发,于是自己也尝试着如如何过去爬虫百科“python”词条等相关页面的整个过程记录下来,方便后期其他人一起来学习。 抓取策略 确定目标:重要的是先确定需要抓取的网站具体的那些部分,下面实例是…...

【Python学习笔记】第二十四节 Python 正则表达式

一、正则表达式简介正则表达式(regular expression)是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特…...

数字逻辑基础:原码、反码、补码

时间紧、不理解可以只看这里的结论 正数的原码、反码、补码相同。等于真值对应的机器码。 负数的原码等于机器码,反码为原码的符号位不变,其余各位按位取反。补码为反码1。 三种码的出现是为了解决计算问题并简化电路结构。 在原码和反码中,存…...

有限差分法-差商公式及其Matlab实现

2.1 有限差分法 有限差分法 (finite difference method)是一种数值求解偏微分方程的方法,它将偏微分方程中的连续变量离散化为有限个点上的函数值,然后利用差分逼近导数,从而得到一个差分方程组。通过求解差分方程组,可以得到原偏微分方程的数值解。 有限差分法是一种历史…...

高校就业信息管理系统

1引言 1.1编写目的 1.2背景 1.3定义 1.4参考资料 2程序系统的结构 3登录模块设计说明一 3.1程序描述 3.2功能 3.3性能 3.4输人项 3.5输出项 3.6算法 3.7流程逻辑 3.8接口 3.10注释设计 3.11限制条件 3.12测试计划 3.13尚未解决的问题 4注册模块设计说明 4.…...

【Java|golang】2373. 矩阵中的局部最大值

给你一个大小为 n x n 的整数矩阵 grid 。 生成一个大小为 (n - 2) x (n - 2) 的整数矩阵 maxLocal ,并满足: maxLocal[i][j] 等于 grid 中以 i 1 行和 j 1 列为中心的 3 x 3 矩阵中的 最大值 。 换句话说,我们希望找出 grid 中每个 3 x …...

根据指定函数对DataFrame中各元素进行计算

【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】根据指定函数对DataFrame中各元素进行计算以下错误的一项是?import numpy as npimport pandas as pdmyDict{A:[1,2],B:[3,4]}myDfpd.DataFrame(myDict)print(【显示】myDf)print(myDf)print(【…...

【蓝桥杯集训·每日一题】AcWing 3502. 不同路径数

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴一、题目 1、原题链接 3502. 不同路径数 2、题目描述 给定一个 nm 的二维矩阵,其中的每个元素都是一个 [1,9] 之间的正整数。 从矩阵中的任意位置出发&#xf…...

Java - 数据结构,二叉树

一、什么是树 概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点: 1、有…...

模拟QQ登录-课后程序(JAVA基础案例教程-黑马程序员编著-第十一章-课后作业)

【案例11-3】 模拟QQ登录 【案例介绍】 1.案例描述 QQ是现实生活中常用的聊天工具,QQ登录界面看似小巧、简单,但其中涉及的内容却很多,对于初学者练习Java Swing工具的使用非常合适。本案例要求使用所学的Java Swing知识,模拟实…...

【壹】嵌入式系统硬件基础

随手拍拍💁‍♂️📷 日期: 2023.2.28 地点: 杭州 介绍: 日子像旋转毒马🐎,在脑海里转不停🤯 🌲🌲🌲🌲🌲 往期回顾 🌲🌲&#x1f332…...

当参数调优无法解决kafka消息积压时可以这么做

今天的议题是:如何快速处理kafka的消息积压 通常的做法有以下几种: 增加消费者数增加 topic 的分区数,从而进一步增加消费者数调整消费者参数,如max.poll.records增加硬件资源 常规手段不是本文的讨论重点或者当上面的手段已经使…...

Java线程池源码分析

Java 线程池的使用,是面试必问的。下面我们来从使用到源码整理一下。 1、构造线程池 通过Executors来构造线程池 1、构造一个固定线程数目的线程池,配置的corePoolSize与maximumPoolSize大小相同, 同时使用了一个无界LinkedBlockingQueue存…...

手撕八大排序(下)

目录 交换排序 冒泡排序: 快速排序 Hoare法 挖坑法 前后指针法【了解即可】 优化 再次优化(插入排序) 迭代法 其他排序 归并排序 计数排序 排序总结 结束了上半章四个较为简单的排序,接下来的难度将会大幅度上升&…...

SAP 详细解析SCC4

事务代码:SCC4,选择一个客户端,点击进入,如图: 一、客户端角色 客户控制:客户的角色(生产性,测试,...) 此属性表示 R/3 系统中的客户端角色。其中可能包括…...

java异常分类和finally代码块中return语句的影响

首先看一下java中异常相关类的继承关系: 引用 1、分类 异常可以分为受查异常和非受查异常,Error和RuntimeException及其所有的子类都是非受查异常,其他的是受查异常。 两者的区别主要在: 受检的异常是由编译器(编译…...

【链表OJ题(二)】链表的中间节点

​ ​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:数据结构 🎯长路漫漫浩浩,万事皆有期待 文章目录链表OJ题(二)1. 链表…...

【强烈建议收藏:MySQL面试必问系列之并发事务锁专题】

一.知识回顾 上节课我们一起学习了MySQL面试必问系列之事务,没有学习的同学可以看一下上一篇文章,肯定对你会有帮助,学习过的同学肯定知道,上节课我们留了一个小尾巴,这个小尾巴是什么呢?就是没有详细展开…...

Linux下使用Makefile实现条件编译

在Linux系统下Makefile和C/C语言都有提供条件选择编译的语法,就是在编译源码的时候,可以选择性地编译指定的代码。这种条件选择编译的使用场合有好多,例如我们开发一个兼容标准版本与定制版本兼容的项目,那么,一些与需…...

java 应用cpu飙升(超过100%)故障排查

前言害。。。昨天刚写完一份关于jvm问题排查相关的博客,今天线上项目就遇到了一个突发问题。现象是用户反映系统非常卡,无法操作。然后登录服务器查看发现cpu 一直100%以上。具体排查步骤:1,首先top命令查看服务器cpu等情况&#…...

光学设计软件Ansys的Lumerical 2023版本下载与安装使用

文章目录前言一、许可管理工具安装二、许可管理器配置三、Lumerical安装四、工具使用配置总结前言 Lumerical是一款功能强大的软件,用于设计和分析从组件到系统阶段的光子学和电磁学。这个版本的Lumerical改进了电子和光子学设计工具,用于复杂光子学&am…...

Java 异常

文章目录1. 异常概述2. JVM 的默认处理方案3. 异常处理之 try...catch4. Throwable 的成员方法5. 编译异常和运行异常的区别6. 异常处理之 throws7. 自定义异常8. throws 和 throw 的区别1. 异常概述 异常就是程序出现了不正常的情况。 ① Error:严重问题&#xff…...

JavaSE学习笔记day17

零、 复习昨日 File: 通过路径代表一个文件或目录 方法: 创建型,查找类,判断类,其他 IO 输入& 输出字节&字符 try-catch代码 一、作业 给定路径删除该文件夹 public static void main(String[] args) {deleteDir(new File("E:\\A"));}// 删除文件夹public s…...

【项目】Vue3+TS 动态路由 面包屑 查询重置 列表

💭💭 ✨:【项目】Vue3TS 动态路由 面包屑 查询重置 列表   💟:东非不开森的主页   💜: 热烈的不是青春,而是我们💜💜   🌸: 如有错误或不足之处&#xff0…...

前脚背完这些接口自动化测试面试题,后脚就进了字节测试岗

1、请结合你熟悉的项目,介绍一下你是怎么做测试的? -首先要自己熟悉项目,熟悉项目的需求、项目组织架构、项目研发接口等 -功能 接口 自动化 性能 是怎么处理的? -第一步: 进行需求分析,需求评审&#…...

termux 安装centos

相关链接 centos官网rootfs制作其他人提供的安装脚本centos镜像列表其他人提供的安装脚本的说明 如果想使用老版本的centos7跟着上面链接5走就行 如果想用新系统比如centos9 stream,就跟我来 Q:为什么要装新系统? A:旧系统太多软件已过时,升级费时费…...

从菜鸟程序员到高级架构师,竟然是因为这个字final

final实现原理 简介 final关键字,实际的含义就一句话,不可改变。什么是不可改变?就是初始化完成之后就不能再做任何的修改,修饰成员变量的时候,成员变量变成一个常数;修饰方法的时候,方法不允…...

开发公司采购招聘/seo关键词分析

最近有个概念吵得很火,网络爬虫,但是基本都是用什么python或者JAVA写,貌似很少看到用c写的,我在网上找了一个,看到其实还是很简单的算法。 算法讲解:1.遍历资源网站 2.获取html信息 3.然后解析网址和图片…...

学做缝纫的网站/网络舆情分析研判报告

install JDKInstall hadoopRun Project on Hadoop install JDK 需要提前安装好jdk和ant。 jdk是对java程序进行编译的工具(java development kid) jre:java runtime environment是提供java虚拟机的运行环境。 ant:项目管理工具…...

如何查一个网站有没有做外链/竞价网站

2.1 数据类型 类型基础: 2.2 类型比较和转换 相等运算符(判断两个操作数没有相同的值)和严格相等(判断两个操作数有没有相同的值以及是否为相同的数据类型) 2.3 函数 基本概念: 函数作用域: …...

专业型企业网站有哪些/广东网站营销seo费用

传送门 分析 从1道m进行匹配&#xff0c;找到第一个不能继续匹配的点即可 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstd…...

网站域名被劫持/西安seo霸屏

到目前为止我们所接触过的角色都是可以接收消息的&#xff0c;而消息的类型也是五花八门&#xff0c;如String、元组、case类/自定义消息等。然而发送消息的行为在感觉上与我们日常编程工作中所使用的常规函数调用还是有很大区别的&#xff0c;为了弥合二者之间的鸿沟&#xff…...

wordpress stheme/免费的个人网页

1.先搞清微信小程序的生命周期和页面生命周期的关系 微信小程序的生命周期包括App生命周期和页面生命周期。App生命周期指的是小程序从启动到退出的整个过程&#xff0c;而页面生命周期则是指小程序中每个页面从创建到销毁的过程。 在小程序中&#xff0c;当用户打开小程序时&a…...