探索Gorm - Golang流行的数据库ORM框架

🏷️个人主页:鼠鼠我捏,要死了捏的主页 

🏷️系列专栏:Golang全栈-专栏

🏷️个人学习笔记,若有缺误,欢迎评论区指正 

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。

前言

我们在之前的专栏中讲解了在Go中如何使用原生的database/sql库完成数据库编程,今天我们继续来了解一下一款在go中常用的数据库ORM框架-Gorm(GORM - The fantastic ORM library for Golang, aims to be developer friendly.)

ORM(Object-Relational Mapping)是一种编程技术,它将对象和关系数据库之间的映射抽象出来,使得开发者可以通过面向对象的方式操作数据库,而不用直接处理SQL语句,相当于在业务逻辑层和数据库层之间一座桥梁。

Gorm是一款用于Golang的ORM框架,它提供了丰富的功能,包括模型定义、数据验证、关联查询等。 Gorm的设计目标是简洁而强大,使得开发者能够更轻松地进行数据库操作


目录

前言

1.安装与配置

安装gorm库

安装mysql驱动

连接url的组成

2.建立连接

自定义mysql配置

自定义gorm配置

调用open对象建立连接,获取连接客户端

扩展:使用AutoMigrate进行表结构同步(根据定义的结构体创建/修改表结构,保证数据结构的一致性,省去手动建表的步骤)

3.基本使用

添加

Create()

Save()

CreateInBatches(records, batchSize)

删除

Delete()

.Unscoped().Delete()

Where().Delete()

修改

db.Save()

db.Model().Update()

db.Updates()

db.UpdateColumn()

db.Where().Update()

查询

db.First()

db.Where().Find()

db.Order()

db.Limit()

db.Offset()

db.Count()

事务

4.其他常用方法

Preload():预加载

目的:减少sql查询次数,避免N+1问题,减少内存开销,适用于复杂关系

基本使用:

Omit():查询中省略指定字段

5.格式化时间字段

总结


1.安装与配置

安装gorm库
go get -u gorm.io/gorm
安装mysql驱动
go get -u gorm.io/driver/mysql
连接url的组成
[DRIVER]://[USER]:[PASS]@[IP]:[PORT]/[DBNAME]?charset=utf8&parseTime=True&loc=Local
  • DRIVER: 数据库驱动名称,如mysql,postgres,sqlite3等

  • USER: 数据库用户名

  • PASS: 数据库密码

  • IP: 数据库主机IP地址,可以是localhost或127.0.0.1等

  • PORT: 数据库端口,默认为3306

  • DBNAME: 数据库名称

  • charset: 字符集,默认utf8

  • parseTime: 是否解析时间字段,默认True

  • loc: 时区,默认Local

示例(mysql连接url)

mysql://root:123123@tcp(127.0.0.1:3306)/testName?charset=utf8mb4&parseTime=True&loc=Local

2.建立连接

自定义mysql配置
mysqlConfig := mysql.Config{DSN:                       dsn,   // 连接urlDefaultStringSize:         255,   // string 类型字段的默认长度DisableDatetimePrecision:  true,  // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引DontSupportRenameColumn:   true,  // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列SkipInitializeWithVersion: false, // 根据版本自动配置
}
自定义gorm配置
gormConfig := &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true,// 使用自定义的logger,gorm默认是将日志输出控制台,使用自定义logger可保存日志到文件Logger:                                   getGormLogger(), 
}
调用open对象建立连接,获取连接客户端
if db, err := gorm.Open(mysql.New(mysqlConfig), gormConfig); err != nil {global.App.Log.Error("mysql connect failed, err:", zap.Any("err", err))return nil} else {global.App.Log.Info("mysql数据库连接成功~~~~~")sqlDB, _ := db.DB()sqlDB.SetMaxIdleConns(dbConfig.MaxIdleConns)sqlDB.SetMaxOpenConns(dbConfig.MaxOpenConns)//数据库表结构同步initMySqlTables(db)return db}

扩展:使用AutoMigrate进行表结构同步(根据定义的结构体创建/修改表结构,保证数据结构的一致性,省去手动建表的步骤)
/*
数据库表结构同步,该方法只会增加新的字段或修改字段,不会删除字段,
AutoMigrate 方法会尝试自动更改表结构,以使其与结构体定义保持一致
*/
func initMySqlTables(db *gorm.DB) {err := db.AutoMigrate(// 需要同步的表的结构体放里面model.User{},model.Media{},)if err != nil {global.App.Log.Error("migrate table failed", zap.Any("err", err))// 退出程序os.Exit(0)}
}

3.基本使用

添加

Create()

添加一条数据,不能重复添加

user := User{Name: "jinzhu"}
db.Create(&user) 
user := User{Name: "jinzhu"}
db.Model(&user).Create(&user)
Save()

添加一条数据,若已存在,则更新对应数据

user := User{Name: "jinzhu"}
db.Save(&user) 
CreateInBatches(records, batchSize)

批量添加数据

  • records:要插入的记录的切片或结构体
  • batchSize:每个批量添加的数量,避免一次性插入太多记录对数据库造成压力
users := []User{{Name: "jinzhu"},{Name: "hello"},
} 
db.CreateInBatches(users, 10)

删除

Delete()

根据结构体Id删除一条数据,若定义了DeletedAt字段,则会进行软删除

db.Delete(&user)
db.Model(&user).Delete(&User{})
.Unscoped().Delete()

忽略软删除直接删除一条数据

db.Unscoped().Delete(&user)
Where().Delete()

根据条件删除多条记录

db.Where("name = ?", "jinzhu").Delete(&User{})

修改

db.Save()

根据结构体主键更新数据

user.Name = "updated"
db.Save(&user) 
db.Model().Update()

通过模型对象更新指定字段

db.Model(&user).Update("name", "new_name")
db.Updates()

批量更新结构体中的字段

db.Model(&user).Updates(User{Name: "new"}) 
db.UpdateColumn()

更新单个字段

db.Model(&user).UpdateColumn("name", "new")
db.Where().Update()

根据条件更新多条记录

db.Where("id=?", 1).Update("name", "updated")

查询

db.First()

查询第一条记录

var user User
db.First(&user, 1) // id = 1 
db.Where().Find()

条件查询多条记录

db.Where("name = ?", "jinzhu").Find(&users)
db.Order()

排序查询

db.Order("age desc").Find(&users) 
db.Limit()

限制返回条数

db.Limit(10).Find(&users)
db.Offset()

分页查询

db.Offset(20).Limit(10).Find(&users)
db.Count()

统计记录数

var count int
db.Find(&users).Count(&count)

事务

tx := db.Begin() //开启事务
tx.Create(&user)
tx.Commit() //提交事务
tx.Rollback() //回滚事务

4.其他常用方法

Preload():预加载

目的:减少sql查询次数,避免N+1问题,减少内存开销,适用于复杂关系
基本使用:

结构体定义:gorm:"foreignKey:problem_id;references:id"指明关联关系,gorm会根据该关系进行预加载。如下面例子中把Struct111的problem_id与ProblemBasic的id关联起来。

// 要使用预加载函数的结构体
type ProblemBasic struct {ID                uint               `gorm:"primarykey;" json:"id"`//  需要预加载的数据Struct1 []*Struct111 `gorm:"foreignKey:problem_id;references:id" json:"problem_categories"` Struct2 *Struct2222 `gorm:"foreignKey:problem_id;references:id;" json:"test_cases"`             
}

使用预加载函数:

err = tx.Preload("Struct1").Preload("Struct2").Find(&problemList).Error

预加载中省略某字段:

err = tx.Preload("Struct1", func(db *gorm.DB) *gorm.DB {return db.Omit("省略的字段名")
}).Preload("Struct2").Find(&problemList).Error

Omit():查询中省略指定字段

tx := DB.Model(&model.ProblemBasic{}).Omit("content")

5.格式化时间字段

当我们使用gorm时,往往需要格式化时间字段来满足使用需求

自定义时间类型,重写其方法

type LocalTime time.Time// 定义 LocalTime 类型在 JSON 编码时的行为
func (t *LocalTime) MarshalJSON() ([]byte, error) {tTime := time.Time(*t)return []byte(fmt.Sprintf("\"%v\"", tTime.Format("2006-01-02 15:04:05"))), nil
}// Value方法即在存储时调用,将该方法的返回值进行存储,该方法可以实现数据存储前对数据进行相关操作
func (t LocalTime) Value() (driver.Value, error) {var zeroTime time.Timetlt := time.Time(t)//判断给定时间是否和默认零时间的时间戳相同if tlt.UnixNano() == zeroTime.UnixNano() {return nil, nil}return tlt, nil
}// Scan方法可以实现在数据查询出来之前对数据进行相关操作
func (t *LocalTime) Scan(v interface{}) error {if value, ok := v.(time.Time); ok {*t = LocalTime(value)return nil}return fmt.Errorf("can not convert %v to timestamp", v)
}

总结

Gorm是一款用于Golang的ORM框架,它提供了丰富的功能,包括模型定义、数据验证、关联查询等。Go提供的原生库已经能够很好的完成数据库编程,而Gorm对其进行了封装,使得数据库操作变得更加简单和灵活。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react【四】css

文章目录 1、css1.1 react和vue css的对比1.2 内联样式1.3 普通的css1.4 css modules1.5 在react中使用less1.6 CSS in JS1.6.1 模板字符串的基本使用1.6.2 styled-components的基本使用1.6.3 接受传参1.6.4 使用变量1.6.5 继承样式 避免代码冗余1.6.6 设置主题色 1.7 React中添…

波奇学Linux:文件缓冲区

问题导入 文件流输出直接向显示器和重定向文件有不一样的表现 分别向显示器文件输出四个语句,最后fork创建子进程。 当程序运行时和程序重定向到文件中,输出的内容不一样。 重定向时c库函数(printf,fprintf,fwrite)调用了两次&…

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)

文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量,叶节点满足,从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现,当不满足条件时直接返回。 到达叶节点后统计答案,用…

片上网络NoC(3)——拓扑指标

目录 一、概述 二、指标 2.1 与网络流量无关的指标 2.1.1 度(degree) 2.1.2 对分带宽(bisection bandwidth) 2.1.3 网络直径(diameter) 2.2 与网络流量相关的指标 2.2.1 跳数(hop coun…

专业140+总分420+浙江大学842信号系统与数字电路考研经验电子信息与通信,真题,大纲,参考书。

今年考研已经结束,初试专业课842信号系统与数字电路140,总分420,很幸运实现了自己的目标,被浙大录取,这在高考是想都不敢想的学校,在考研时实现了,所以大家也要有信心,通过自己努力实…

综合例题及补充

目录 查询员工的编号、姓名、雇佣日期,以及计算出每一位员工到今天为止被雇佣的年数、月数、天数 计算出年 计算月 计算天数 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 查询员工的编号、姓名、雇佣日期&#xff0c…

【开源】基于JAVA+Vue+SpringBoot的学生综合素质评价系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生功能2.2 教师功能2.3 教务处功能 三、系统展示四、核心代码4.1 查询我的学科竞赛4.2 保存单个问卷4.3 根据类型查询学生问卷4.4 填写语数外评价4.5 填写品德自评问卷分 五、免责说明 一、摘要 1.1 项目介绍 基于J…

【Spring】Bean 的作用域

一、singleton 默认情况下,Spring 的 IoC 容器创建的 Bean 对象是单例的(单例模式) 默认情况下,Bean 对象的创建是在初始化 Spring 上下文的时候就完成的 package org.qiu.spring.bean;/*** author 秋玄* version 1.0* email q…

【c++基础】温度统计员

说明 炎热的夏日&#xff0c;KC非常的不爽。他宁可忍受北极的寒冷&#xff0c;也不愿忍受厦门的夏天。最近&#xff0c;他开始研究天气的变化。他希望用研究的结果预测未来的天气。 经历千辛万苦&#xff0c;他收集了连续N&#xff08;1<N<10000&#xff09;天的最高气温…

idea:如何连接数据库

1、在idea中打开database: 2、点击 ‘’ ---> Data Source ---> MySQL 3、输入自己的账号和密码其他空白处可以不填&#xff0c;用户和密码可以在自己的mysql数据库中查看 4、最后选择自己需要用的数据库&#xff0c;点击运用ok&#xff0c;等待刷新即可 最后&#xff1a…

C# EventHandler<T> 示例

新建一个form程序&#xff0c;在调试窗口输出执行过程&#xff1b; 为了使用Debug.WriteLine&#xff0c;添加 using System.Diagnostics; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using S…

celery异步框架的使用

文章目录 celery的介绍celery的架构celery的快速使用celery 包结构celery 定时 异步 延迟任务django使用celery celery的介绍 celery是什么&#xff1f; -翻译过来是芹菜 -官网&#xff1a;https://docs.celeryq.dev/en/stable/ -吉祥物&#xff1a;芹菜 -分布式的异步任务框架…