go-zerogo web集成gorm实战

news2024/7/4 5:22:14

前言

上一篇:go-zero&go web集成redis实战

从零开始基于go-zero搭建go web项目实战-04集成gorm实战
源码仓库地址 源码 https://gitee.com/li_zheng/treasure-box

golang gorm

官网地址:https://gorm.io/zh_CN/docs/index.html

GORM介绍

Gorm是Go语言目前比较热门的数据库ORM库,API简单明了,上手容易,使用简单,主要把struct类型和数据库表记录进行映射,操作数据库的时候不需要直接手写SQL,面向结构体,同时也支持手动编写sql进行调优。

特性

  • 全功能 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 官方支持的数据库类型有:MySQL, PostgreSQL, SQLite, SQL Server 和 TiDB

安装

这里使用MySQL数据库进行测试
安装依赖包

// 安装MySQL依赖
go get gorm.io/driver/mysql@v1.3.5
// 安装Gorm依赖
go get gorm.io/gorm@v1.25.4

简单入门

创建mysql数据库连接

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

func main() {
  //连接本地数据库bd01,用户名:root,密码:123456
  dsn := "root:123456@tcp(127.0.0.1:3306)/db01?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
  • mysql.Open(dsn) 根据提供的连接信息打一个mysql连接器
  • gorm.Open() 在给定 dialector 的基础上开启一个 db session
  • gorm.Config{} 可选配置

声明一个模型struct,对应数据的一张表,User继承了gorm.Model,拥有gorm.Model的字段信息。

type User struct {
	gorm.Model
	Name    string
	Sex     int8
}
// 指定表名 t_user
func (User) TableName() string {
	return "t_user"
}

// gorm.Model 的定义,提供默认的字段和类型,GORM 约定使用 CreatedAt、UpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间
type Model struct {
ID uint gorm:"primaryKey"
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt gorm:"index"
}

操作数据库,这里给出几个例子,更多操作方式见官网

  // 迁移 schema
  db.AutoMigrate(&User{})

  // Create
  db.Create(&User{Name: "张三", Sex: 1})

  // Read
  var user User
  db.First(&user, 1) // 根据整型主键查找
  db.First(&user, "name = ?", "张三") // 查找 code 字段值为 D42 的记录

  // Update
  db.Model(&user).Update("Name", "李四")
  // Update - 更新多个字段
  db.Model(&user).Updates(User{Name: "王五", Sex: 2}) // 仅更新非零值字段
  db.Model(&user).Updates(map[string]interface{}{"Name": '王五', "Sex": 2})

  // Delete - 删除 product
  db.Delete(&user, 1)

Web集成

新增配置struct

在项目原有基础上新增一个数据配置结构体,添加到全局配置 Config 中

type DbConf struct {
	Host                     string
	Port                     int
	Username                 string
	Password                 string
	Db                       string
	ParamStr                 string `json:",optional"`
	MaxOpenConns             int    `json:",default=10"`
	MaxIdleConns             int    `json:",default=5"`
	ConnMaxIdleTime          int    `json:",default=60"`
	ConnMaxLifetime          int    `json:",default=60"`
	SlowThresholdMillisecond int64  `json:",default=1000"`
}

type Config struct {
	rest.RestConf
	Redis redis.RedisConf `json:",optional"`
	Auth  struct {
		AccessSecret string
		AccessExpire int64
	}
	Db DbConf `json:",optional"`
}

yaml中配置数据库

Db:
  Host: localhost
  Port: 3306
  Username: root
  # 这里密码如果是纯数字需要加引号
  Password: "123456"
  # 数据库名
  Db: test01
  #连接参数字符串拼接形式
  ParamStr: charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai
  #设置打开数据库连接的最大数量
  MaxOpenConns: 10
  #设置空闲连接池中连接的最大数量
  MaxIdleConns: 5
  #连接最大空闲时间 单位秒
  ConnMaxIdleTime: 60
  #设置连接可复用的最大时间 单位秒
  ConnMaxLifetime: 60

项目启动加载配置

这里使用的是go-zero的conf.MustLoad(configFile, &c)方法加载yaml配置,其他方式可自行根据情况进行配置读取,例如使用 gopkg.in/yaml.v2 进行读取。

conf.MustLoad(configFile, &c)

在这里插入图片描述
gopkg.in/yaml.v2 读取例子


func LoadAppConf(filePath string, out interface{}) error {
	file, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	err = yaml.Unmarshal(file, out)
	if err != nil {
		return err
	}
	if conf.Logging.PrintConf {
		fmt.Println("------------------------------------------", filePath, " Start------------------------------------------>")
		fmt.Println(string(file))
		fmt.Println()
	}

	return nil
}

初始化数据库连接

在项目上下文中初始化数据库连接信息,internal/svc/ctx.go 中的 initDb 方法会在服务启动时候调用,进行数据库的初始化,具体代码如下,调用细节可以参考:https://gitee.com/li_zheng/treasure-box 下对应的文件代码

func initDb() {
	dbConf := sCtx.Config.Db
	if len(dbConf.Host) == 0 {
		return
	}
	logx.Infof("Initializing db ...")
	//if len(dbConf.ParamStr) == 0 {
	//	dbConf.ParamStr = getParamStr(dbConf.ConnParams)
	//}
	dbUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s",
		dbConf.Username,
		dbConf.Password,
		dbConf.Host,
		dbConf.Port,
		dbConf.Db,
		dbConf.ParamStr)
	logx.Infof("DSN: %s", dbUrl)
	dialector := mysql.New(mysql.Config{
		DSN:                       dbUrl, // data source name
		DefaultStringSize:         256,   // string 类型字段的默认长度
		DisableDatetimePrecision:  true,  // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
		DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
		DontSupportRenameColumn:   true,  // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
	})

	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)
		logger.Config{
			SlowThreshold:             time.Duration(dbConf.SlowThresholdMillisecond) * time.Millisecond, // 慢 SQL 阈值
			LogLevel:                  logger.Info,                                                       // 日志级别
			IgnoreRecordNotFoundError: true,                                                              // 忽略ErrRecordNotFound(记录未找到)错误
			Colorful:                  true,                                                              // 禁用彩色打印
		},
	)

	option := &gorm.Config{
		//禁用默认全局事务
		SkipDefaultTransaction: true,
		//开启预编译sql
		PrepareStmt: true,
		Logger:      newLogger,
	}
	db, err := gorm.Open(dialector, option)
	if err != nil {
		logx.Must(err)
	}
	sqlDb, err := db.DB()
	if err != nil {
		logx.Must(err)
	}
	sqlDb.SetMaxOpenConns(dbConf.MaxOpenConns)
	sqlDb.SetMaxIdleConns(dbConf.MaxIdleConns)
	sqlDb.SetConnMaxIdleTime(time.Second * time.Duration(dbConf.ConnMaxIdleTime))
	sqlDb.SetConnMaxLifetime(time.Second * time.Duration(dbConf.ConnMaxLifetime))
	sCtx.Db = db
	logx.Infof("%+v", sqlDb.Stats())
	logx.Infof("DB Initialized.")
}

项目中使用

在这里插入图片描述

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

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

相关文章

Postman —— HTTP请求基础组成部分

一般来说,所有的HTTP Request都有最基础的4个部分组成:URL、 Method、 Headers和body。 (1)Method 要选择Request的Method是很简单的,Postman支持所有的请求方式。 (2)URL 要组装一条Request…

Pytorch Advanced(二) Variational Auto-Encoder

自编码说白了就是一个特征提取器,也可以看作是一个降维器。下面找了一张很丑的图来说明自编码的过程。 自编码分为压缩和解码两个过程。从图中可以看出来,压缩过程就是将一组数据特征进行提取, 得到更深层次的特征。解码的过程就是利用之前的…

python-爬虫-urllib

网络爬虫(Web Crawler),又叫网络蜘蛛、网络机器人,是一种自动化数据采集程序 数据采集 → 数据处理 → 数据存储 常见的工作流程如下: 1.定义采集的目标(网站、APP、公众号、小程序)&#xff…

RP9学习-2

1.基本元素2 1.1树 可以收起 添加子菜单 选中树的节点即可添加 移动层级 编辑树属性 选中某行文字,点击Edit Tree Properties 可以把箭头变成加减,另外也可以导入自己的图标 注意要使用自己的图标,需要勾选Show Icon 也可以给某个节点单…

开放式耳机也会有巅峰音质体验-南卡NANK OE PRO

前言 这两年,开放式耳机市场发展迅猛,新品层出不穷,各大耳机厂商也都相继推出了自家的产品。而在众多的厂家中,作为国内开发式耳机的TOP1,南卡通过多年来在业内领域的经验和专业的技术能力,为广大音乐爱好…

fastadmin在前端调用 /api/common/upload 返回未上传文件或超出服务器上传限制

第一步:在api目录直接调用 域名/api/common/upload 上传图片的时候要在Common.php文件里面把验证登录的 protected $noNeedLogin [init]; 方法注释掉。 // protected $noNeedLogin [init];protected $noNeedLogin *;protected $noNeedRight *; 第二步&#…

计算机竞赛 大数据分析:基于时间序列的股票预测于分析

1 简介 Hi,大家好,这里是丹成学长,今天向大家介绍一个大数据项目 大数据分析:基于时间序列的股票预测于分析 2 时间序列的由来 提到时间序列分析技术,就不得不说到其中的AR/MA/ARMA/ARIMA分析模型。这四种分析方法…

dp(1) - 数字三角形模型

898.数字三角形 题目链接 : 活动 - AcWing 题目 : 给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和…

利用LinuxPTP进行时间同步(软/硬件时间戳) - 研一

转自:https://blog.csdn.net/BUPTOctopus/article/details/86246335 官方文档:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s1-using_ptp 查看网卡是否支持软硬件时间戳: sudo ethtoo…

为什么做期权卖方是比较高胜率的?

期权三大因素:行情方向、时间价值流失、波动率。波动率下降、时间价值流失,震荡行情,这几项对期权卖方交易有利,一般做期权卖方胜率基本可以达70%左右,下文揭秘为什么做期权卖方是比较高胜率的? 一、期权卖方交易如何…

MQTT网关对接水务二次供水管理平台案例

一、客户介绍 随着城市发展和人口增长,对水务行业的监测和管理要求也越来越高。然而,传统的水务行业监测方式存在很多不足,如数据传输的缓慢和不可靠,数据安全风险大等,为了更有效地监测和管理这些信息,供…

电子科大软件系统架构设计——系统规划

文章目录 系统规划定义意义目标任务路径规划规划步骤规划方法业务系统规划法业务流程重组法价值链分析法战略目标集转移法关键成功因素法 项目计划定义要素工作分解活动排序工期预算三点估计法德尔菲法 成本估算与计算进度安排甘特图法PERT图方法 可行性分析技术可行性分析进度…

固定资产电脑怎么编号管理

科技的发展已经深入到了我们的生活中的每一个角落,尤其是在办公室环境中,电脑已经成为了必不可少的工具。然而,随着电脑数量的增加和管理复杂性的提升,如何有效地管理和追踪这些固定资产变得越来越重要。本文将探讨一种创新的方式…

Scrum敏捷开发如何实施

​在当今高度变化的时代,软件开发的环境和要求也在不断变化。传统的开发方法往往难以适应这种快速变化,因此,一种新的软件开发方法——敏捷开发逐渐得到了广泛的关注和应用。 敏捷开发的实施可以按照以下步骤进行: 1、明确产品愿…

WebDAV之π-Disk派盘 + 飞傲音乐

飞傲音乐是一款专为手机解码耳放设计的本地播放器,旨在提供更符合发烧友使用习惯的音乐播放体验。它具备以下功能和特性: 1. DSD源码输出:支持DSD音频格式的输出,即使是普通手机也能够进行DSD硬解码播放。 2. Hi-Res高清音乐格式源码输出:支持高清音乐格式,可以播放高达…

led护眼灯真的能护眼吗?Led护眼灯的好处

随着人们对家庭环境艺术的重视,台灯因其摆设在桌案台几上的特殊地位,也要进求特有的装饰效果。家居用台灯开始逐新分流为工艺台灯和书写台灯两类。前者追求外观效果,将发展思路放在材质的创新、造型的求异上,以配合风格多样的家居…

字符串类型

目录 一、字符与字符串 二、字符串对象与自变量 三、正则表达式 1.普通字符 2.特殊字符 3.非打印字符 4.限定符 5.定位符 四、正则表达式的处理 1.Pattern.compile(String regex) 2.Matcher.matches() 3.Matcher.find() 4.Matcher.replaceAll(String replacement)…

CRM客户管理系统是什么?

CRM的含义我们都知道,是客户关系管理的缩写,更多地用来代表CRM系统。所以CRM管理又可以理解为通过CRM系统进行管理。那么下面我们就来详细说说,什么是crm管理? CRM管理功能主要包括: 营销管理: CRM系统可…

【规范】Apifox就应该这么玩

前言 🍊缘由 好的工具就要配好的玩法 起因是最近在回顾项目时,看到了年事已高并且长时间不用的Postman,发现之前自己整理的接口文档十分混乱且没有规律。遂打开现在使用的Apifox,将本狗目前项目中使用Apifox的整理规范和使用方…

【数据结构前置知识】初识集合框架和时间,空间复杂度

文章目录 1. 什么是集合框架2. 集合框架的重要性 3. 背后所涉及的数据结构以及算法3.1 什么是数据结构3.2 容器背后对应的数据结构3.3 相关java知识3.4 什么是算法 4.时间复杂度1. 如何衡量一个算法的好坏2. 算法效率3. 时间复杂度3.1 时间复杂度的概念3.2 大O的渐进表示法3.3 …