Go语言之GORM框架(二) ——GORM的单表操作

2024-05-27 03:12
文章标签 语言 go 操作 单表 框架 gorm

本文主要是介绍Go语言之GORM框架(二) ——GORM的单表操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在上一篇文章中,我们对Gorm进行了介绍,而在这一篇文章中我们主要介绍GORM的单表查询与Hook函数,在进行今天的内容之前我们先事先说明一下,下面我们对单表进行操作的表结构如下:

type Student struct {ID   uint   `gorm:"size:3"`Name string `gorm:"size:8"`Age  int    `gorm:"size:3"`Sex  string `gorm:"size:3"`Email *string `gorm:"size:32"`
}

好了,话不多说,开始我们今天的内容

表的初始化

在这里插入图片描述
首先我们确定一下我们已经将要演示的数据库内相关内容清空掉了,然后我们就可以开始连接数据库并创建students表了:

package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)type Student struct {ID    uint    `gorm:"size:3"`Name  string  `gorm:"size:8"`Age   int     `gorm:"size:3"`Sex   string  `gorm:"size:3"`Email *string `gorm:"size:32"`
}var myDB *gorm.DBfunc init() {user := "root"password := "aaaa"dbname := "gorm"ip := "127.0.0.1"port := "3306"dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, password, ip, port, dbname)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {fmt.Println("数据库连接失败,err:", err)return}fmt.Println("数据库连接成功")myDB = db
}func main() {err := myDB.AutoMigrate(&Student{})if err != nil {fmt.Println("students表创建失败,err:", err)return}fmt.Println("students表创建成功")
}

在这里插入图片描述

单表操作

创建并插入数据

插入单条数据

func SingleInsert(student Student) {res := myDB.Create(&student)if res.Error != nil {fmt.Println("插入数据失败,err:", res.Error)return}fmt.Println("插入数据成功")
}func main() {err := myDB.AutoMigrate(&Student{})if err != nil {fmt.Println("students表创建失败,err:", err)return}fmt.Println("students表创建成功")email := "fengxu@163.com"student := Student{Name:  "fengxu",Age:   18,Sex:   "男",Email: &email,}SingleInsert(student)
}

运行成功,查找数据库:
在这里插入图片描述
这样我们就成功将一条记录插入数据库了

批量插入数据

func Insert(StudentList []Student) {var StudentList []Studentfor i := 0; i < 10; i++ {email := fmt.Sprintf("No.%d@163.com", i)student := Student{Name:  fmt.Sprintf("No.%d", i),Age:   18 + i,Sex:   "男",Email: &email,}StudentList = append(StudentList, student)}res := myDB.Create(&StudentList)if res.Error != nil {fmt.Println("插入数据失败,err:", res.Error)return}fmt.Println("插入数据成功")
}

在这里插入图片描述
这显示我们成功向students表中批量插入数据。

插入数据的细节

  • 这里的email我为了表示它可以为空,将它的类型设置成了指针,所以我们在传值的时候也要传指针
  • 我们在使用Create函数时,传递的是指针,而不是具体值
  • 由于我们传入到Create函数的是student的指针,所以student在此之后就会出现该记录的其他消息了,比如下面这样:
func SingleInsert(student Student) {//插入单条数据email := "fengxu@163.com"student := Student{Name:  "luoyu",Age:   18,Sex:   "男",Email: &email,}SingleInsert(student)res := myDB.Create(&student)if res.Error != nil {fmt.Println("插入数据失败,err:", res.Error)return}fmt.Println("插入数据成功")fmt.Println(student)
}

打印的结果为:

{13 luoyu 180xc0001e0830}

单表插入的完整代码:

package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)type Student struct {ID    uint    `gorm:"size:3"`Name  string  `gorm:"size:8"`Age   int     `gorm:"size:3"`Sex   string  `gorm:"size:3"`Email *string `gorm:"size:32"`
}var myDB *gorm.DBfunc init() {user := "root"password := "ba161754"dbname := "gorm"ip := "127.0.0.1"port := "3306"dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, password, ip, port, dbname)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {fmt.Println("数据库连接失败,err:", err)return}fmt.Println("数据库连接成功")myDB = db
}func SingleInsert(student Student) {res := myDB.Create(&student)if res.Error != nil {fmt.Println("插入数据失败,err:", res.Error)return}fmt.Println("插入数据成功")fmt.Println(student)
}func Insert(StudentList []Student) {res := myDB.Create(&StudentList)if res.Error != nil {fmt.Println("插入数据失败,err:", res.Error)return}fmt.Println("插入数据成功")
}func main() {err := myDB.AutoMigrate(&Student{})if err != nil {fmt.Println("students表创建失败,err:", err)return}fmt.Println("students表创建成功")//插入单条数据email := "fengxu@163.com"student := Student{Name:  "luoyu",Age:   18,Sex:   "男",Email: &email,}SingleInsert(student)//批量插入数据var StudentList []Studentfor i := 0; i < 10; i++ {email := fmt.Sprintf("No.%d@163.com", i)student := Student{Name:  fmt.Sprintf("No.%d", i),Age:   18 + i,Sex:   "男",Email: &email,}StudentList = append(StudentList, student)}Insert(StudentList)
}

单表查询

前言

在讲解单表查询之前,我们先来看一个很简单的单表查询代码

package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log""os""time"
)type Student struct {ID    uint    `gorm:"size:3"`Name  string  `gorm:"size:8"`Age   int     `gorm:"size:3"`Sex   string  `gorm:"size:3"`Email *string `gorm:"size:32"`
}var myDB *gorm.DB
var mysqllogger logger.Interfacefunc init() {user := "root"password := "ba161754"dbname := "gorm"ip := "127.0.0.1"port := "3306"dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, password, ip, port, dbname)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {fmt.Println("数据库连接失败,err:", err)return}fmt.Println("数据库连接成功")myDB = db
}func initLogger() {var mysqlLogger logger.InterfacemysqlLogger = logger.Default.LogMode(logger.Info) //设置日志打印级别mysqlLogger = logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // (日志输出的目标,前缀和日志包含的内容)logger.Config{SlowThreshold:             time.Second, // 慢 SQL 阈值LogLevel:                  logger.Info, // 日志级别IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound(记录未找到)错误Colorful:                  true,        // 使用彩色打印},)myDB.Logger = mysqlLogger
}func main() {var student StudentinitLogger()myDB.Session(&gorm.Session{Logger: mysqllogger,})myDB.Take(&student) //默认查找第一条数据fmt.Println(student)student = Student{}myDB.First(&student) //查找第一条数据fmt.Println(student)student = Student{}myDB.Last(&student) //查找最后一条数据fmt.Println(student)
}

输出结果为:
在这里插入图片描述
这里我在打印出查询结果的同时也打印出了它们原生的sql语句,我们可以看到相对于原生sql语句,GORM的语句相对比较简单。

当然和我们平时利用各种各样的筛选条件来进行查询,我们在GORM也可以利用各种各样的条件来完成查询,,最后我们介绍一下下面我们可能会使用的函数:

  • Take:用于从数据库中检索符合条件的第一条记录,并将其填充到指定的结构体中。如果没有指定特定的条件,它会默认返回第一条记录。
  • Find:用于从数据库中检索符合条件的所有记录,并将它们填充到指定的结构体切片中。你可以使用Where函数来添加条件限制,以便只检索满足特定条件的记录。

单条记录查询

  • 根据主键查询
	myDB.Take(&student, 1)fmt.Println(student)myDB.Take(&student, "1")fmt.Println(student)

注意:这里指定主键时可以是数字也可以是字符串

  • 根据其他条件来查询
	myDB.Take(&student, "name = ?", "fengxu")fmt.Println(student)

这里我们用?来作为占位符,这样可以有效的防止sql注入

  • 根据struct来查询
	myDB.Where(&Student{Name: "fengxu"}).Find(&student)fmt.Println(student)student = Student{}
  • 获取查询结果
	var studentList []Studenterr := myDB.Find(&studentList).Errorswitch {case errors.Is(err, gorm.ErrRecordNotFound):fmt.Println("没有找到数据")default:fmt.Println("sql语句出现问题")}count := myDB.Find(&studentList).RowsAffected  //获取查询结果条数fmt.Println(count)
}

完整代码:

func SingleSerach() {var student Studentvar studentList []Student//根据主键查询myDB.Take(&student, 1)fmt.Println(student)student = Student{}myDB.Take(&student, "3")fmt.Println(student)student = Student{}//根据字段查询myDB.Take(&student, "name = ?", "fengxu")fmt.Println(student)student = Student{}//根据struct来查询//student.ID = 4myDB.Where(&Student{Name: "fengxu"}).Find(&student)fmt.Println(student)student = Student{}err := myDB.Find(&studentList).Errorswitch {case errors.Is(err, gorm.ErrRecordNotFound):fmt.Println("没有找到数据")default:fmt.Println("sql语句出现问题")}count := myDB.Find(&studentList).RowsAffectedfmt.Println(count)
}

多条记录查询

  • 简单示例:
func MultipleSearch() {var studentList []StudentmyDB.Find(&studentList)for _, v := range studentList {fmt.Println(v)}//上面我们打印的email是地址,我们需要对它进行序列化for _, v := range studentList {data, _ := json.Marshal(v)fmt.Println(string(data))}
}
  • 按照主键来查询
	studentList1 := []Student{}myDB.Find(&studentList1, 1, 2, 3, 4, 5, 6)for _, v := range studentList1 {data, _ := json.Marshal(v)fmt.Println(string(data))}studentList2 := []Student{}myDB.Find(&studentList2, []int{1, 2, 3, 4, 5, 6})for _, v := range studentList2 {data, _ := json.Marshal(v)fmt.Println(string(data))}

注意:这里其实用不用前片都可以,但是测试结果是切片速度明显较快,建议使用切片

  • 按照其他条件来查询
	//根据字段查询studentList := []Student{}myDB.Where("name in ?", []string{"fengxu", "luoyu"}).Find(&studentList)for _, v := range studentList {data, _ := json.Marshal(v)fmt.Println(string(data))}

全部代码:

func MultipleSearch() {var studentList []StudentmyDB.Find(&studentList)for _, v := range studentList {fmt.Println(v)}//按主键查询studentList1 := []Student{}myDB.Find(&studentList1, 1, 2, 3, 4, 5, 6)for _, v := range studentList1 {data, _ := json.Marshal(v)fmt.Println(string(data))}studentList2 := []Student{}myDB.Find(&studentList2, []int{1, 2, 3, 4, 5, 6})for _, v := range studentList2 {data, _ := json.Marshal(v)fmt.Println(string(data))}//根据字段查询studentList = []Student{}myDB.Where("name in ?", []string{"fengxu", "luoyu"}).Find(&studentList)for _, v := range studentList {data, _ := json.Marshal(v)fmt.Println(string(data))}
}

单表数据的更新

示例:

func Update() {var student StudentmyDB.Take(&student, 1)student.Name = "三玖"student.Sex = "女"myDB.Save(&student)fmt.Println(student)
}

注意:

  • Save会保留所有的字段,哪怕我们将字段的值设为0
  • Save函数其实是一个组合操作,如果当前不存在该字段,则是执行Create否则执行Update
  • 不要将 SaveModel一同使用, 这是 未定义的行为

单列更新

  • 更新单列指定字段
	//更新指定字段student = Student{}myDB.Take(&student)student.Age = 19myDB.Select("age").Save(&student)fmt.Println(student)
  • 批量更新
	//同时更新单个指定字段studentList := []Student{}myDB.Where("name like ?", "No.%").Find(&studentList).Update("age", 19)for _, v := range studentList {fmt.Println(v.Name, v.Age)}//同时更新多个指定字段Email := "sanjiu@163.com"new_student := Student{Age:   20,Sex:   "女",Email: &Email,}myDB.Model(&student).Where("name=?", "三玖").Updates(new_student)  //方法一:structmyDB.Model(&student).Where("name=?", "三玖").Updates(map[string]interface{}{"age":   20,"sex":   "女","email": "sanjiu@163.com",})//  方法二:map

注意:Updates函数在struct方法更新字段时会自动忽略零值,如果想避免建议使用map或使用Select函数说明一下要更新的字段,示例如下:

DB.Model(&Student{}).Where("age = ?", 21).Select("gender", "email").Updates(Student{Email:  &email,Gender: false,
})

单表删除

func Delete() {var student Studentvar studentlist []StudentmyDB.Take(&student, 1)myDB.Delete(&student) //单行删除myDB.Take(&studentlist, []int{1, 2, 3})myDB.Delete(&studentlist) //批量删除
}

代码汇总

以上有关单表操作的全部代码:

package mainimport ("encoding/json""errors""fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log""os""time"
)type Student struct {ID    uint    `gorm:"size:3"`Name  string  `gorm:"size:8"`Age   int     `gorm:"size:3"`Sex   string  `gorm:"size:3"`Email *string `gorm:"size:32"`
}var myDB *gorm.DB
var mysqllogger logger.Interfacefunc init() {user := "root"password := "nicai"dbname := "gorm"ip := "127.0.0.1"port := "3306"dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, password, ip, port, dbname)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {fmt.Println("数据库连接失败,err:", err)return}fmt.Println("数据库连接成功")myDB = db
}func initLogger() {var mysqlLogger logger.InterfacemysqlLogger = logger.Default.LogMode(logger.Info) //设置日志打印级别mysqlLogger = logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // (日志输出的目标,前缀和日志包含的内容)logger.Config{SlowThreshold:             time.Second, // 慢 SQL 阈值LogLevel:                  logger.Info, // 日志级别IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound(记录未找到)错误Colorful:                  true,        // 使用彩色打印},)myDB.Logger = mysqlLogger
}func SingleSerach() {var student Studentvar studentList []Student//根据主键查询myDB.Take(&student, 1)fmt.Println(student)student = Student{}myDB.Take(&student, "3")fmt.Println(student)student = Student{}//根据字段查询myDB.Take(&student, "name = ?", "fengxu")fmt.Println(student)student = Student{}//根据struct来查询//student.ID = 4myDB.Where(&Student{Name: "fengxu"}).Find(&student)fmt.Println(student)student = Student{}err := myDB.Find(&studentList).Errorswitch {case errors.Is(err, gorm.ErrRecordNotFound):fmt.Println("没有找到数据")default:fmt.Println("sql语句出现问题")}count := myDB.Find(&studentList).RowsAffectedfmt.Println(count)
}func MultipleSearch() {var studentList []StudentmyDB.Find(&studentList)for _, v := range studentList {fmt.Println(v)}//按主键查询studentList1 := []Student{}myDB.Find(&studentList1, 1, 2, 3, 4, 5, 6)for _, v := range studentList1 {data, _ := json.Marshal(v)fmt.Println(string(data))}studentList2 := []Student{}myDB.Find(&studentList2, []int{1, 2, 3, 4, 5, 6})for _, v := range studentList2 {data, _ := json.Marshal(v)fmt.Println(string(data))}//根据字段查询studentList = []Student{}myDB.Where("name in ?", []string{"fengxu", "luoyu"}).Find(&studentList)for _, v := range studentList {data, _ := json.Marshal(v)fmt.Println(string(data))}
}func Update() {//update操作示例var student StudentmyDB.Take(&student, 1)student.Name = "三玖"student.Sex = "女"myDB.Save(&student)fmt.Println(student)//更新指定字段student = Student{}myDB.Take(&student)student.Age = 19myDB.Select("age").Save(&student)fmt.Println(student)//同时更新多列的指定字段studentList := []Student{}myDB.Where("name like ?", "No.%").Find(&studentList).Update("age", 19)for _, v := range studentList {fmt.Println(v.Name, v.Age)}//同时更新多列Email := "sanjiu@163.com"new_student := Student{Age:   20,Sex:   "女",Email: &Email,}myDB.Model(&student).Where("name=?", "三玖").Updates(new_student) //方法一:structmyDB.Model(&student).Where("name=?", "三玖").Updates(map[string]interface{}{"age":   20,"sex":   "女","email": "sanjiu@163.com",}) //  方法二:map
}func Delete() {var student Studentvar studentlist []StudentmyDB.Take(&student, 1)myDB.Delete(&student) //单行删除myDB.Take(&studentlist, []int{1, 2, 3})myDB.Delete(&studentlist) //批量删除
}func main() {//var student StudentinitLogger()myDB.Session(&gorm.Session{Logger: mysqllogger,})//myDB.Take(&student) //默认查找第一条数据//fmt.Println(student)//student = Student{}////myDB.First(&student) //查找第一条数据//fmt.Println(student)//student = Student{}////myDB.Last(&student) //查找最后一条数据//fmt.Println(student)Delete()
}

结语

上面仅仅是我基于Gorm框架学习的一些笔记,详细可以参考:
GORM官方文档

这篇关于Go语言之GORM框架(二) ——GORM的单表操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1006363

相关文章

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

Python 中的 with open文件操作的最佳实践

《Python中的withopen文件操作的最佳实践》在Python中,withopen()提供了一个简洁而安全的方式来处理文件操作,它不仅能确保文件在操作完成后自动关闭,还能处理文件操作中的异... 目录什么是 with open()?为什么使用 with open()?使用 with open() 进行

Linux ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处