【GORM框架】一文学会用gorm实现对单表的增删改查操作

news2024/12/23 13:12:49

在这里插入图片描述

  • 博主简介:努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:数据结构、Go,Java等相关知识。
  • 博主主页: @是瑶瑶子啦
  • 所属专栏: GORM框架学习
  • 近期目标:写好专栏的每一篇文章

在这里插入图片描述

文章目录

  • 一、准备工作
  • 二、增(Create)
    • 1.1:添加一条记录
    • 1.2:批量插入
  • 三、查询
    • 3.1:查询单条记录
    • 3.2:查询多条记录
    • 3.3:获取查询结果
  • 四、改
  • 五、删除

一、准备工作

在上一篇Gorm文章中,我们学习了如何使用gorm进行数据库的连接和一些高级配置、简单操作。👉【GORM框架】模型定义超详解,确定不来看看?

今天,我们要学习,如何使用gorm,进行单表的CRUD操作

在学习CRUD之前,这是一些准备工作:

有一个golang项目,其中连接是只负责和数据库进行连接
在这里插入图片描述

package main

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

var DB *gorm.DB

func init() {
	username := "root"     //账号
	password := "55667788" //密码
	host := "127.0.0.1"    //数据库地址,可以是Ip或者域名(这里用的就是localhost,是一个回送地址,值本地机
	port := 3306           //数据库端口
	Dbname := "testdb"     //数据库名
	timeout := "10s"       //连接超时,10秒

	// root:root@tcp(127.0.0.1:3306)/gorm?
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn))
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
	// 连接成功
	fmt.Println(db)
	//把其DB类型实例赋给定义好的全局变量
	DB = db
}

再新建文件.go文件,进行CRUD练习

按住ctrl,点击多个.go文件,再右键go run,即可一次性运行多个go文件,但是注意,只能有一个main函数

这是模型定义:


// 1)模型定义:(表结构)
type Student struct {
	ID     uint   `gorm:"size:3"`
	Name   string `gorm:"size:8"`
	Age    int    `gorm:"size:3"`
	Gender byte
	Email  *string `gorm:"size:32"`
}

注意!!!

  • 为什么要把Email定义成指针类型呢?是为了更好的存储null类型。
  • 因为string在Go中是值类型,当string没有被赋值时,默认是空串""。它是长度为0,同样占存储空间的字符串。而不是明显的告诉我们:这是一个空!!这样会引起混淆
  • 相比之下,用指针类型,如果没有给出email,那就直接是空:null,既不会引起混淆,也可以节省空间(因为不会开辟内存)

二、增(Create)

1.1:添加一条记录

记录对应到代码里,其实就是结构体实体,所以我们只需实例化结构体,再使用gorm函数,进行create,即可建立联系,在数据库中增加记录

func main() {
	//2)建表
	DB.AutoMigrate(&Student{})

	//3)添加记录(实例化结构体)
	email := "3051337060@qq.com"
	s1 := Student{
		Name:   "瑶瑶子",
		Age:    19,
		Gender: 'F',
		Email:  &email,
	}
	//把该实体映射到表中的记录:
	err := DB.Create(&s1).Error
	fmt.Println(err)
}

注意!!!

  • Create函数接收的是指针

1.2:批量插入

批量插入也是用到Create方法,需要使用到Go中的切片

//批量插入记录
	//1)首先定义一个切片,用于存储多条记录
	var studentList []Student

	//2)向切片输入
	for i := 0; i < 100; i++ {
		studentList = append(studentList, Student{
			Name:   fmt.Sprintf("瑶瑶子%d号", i+1),
			Age:    19,
			Gender: 'F',
			Email:  &email,
		})
	}

	//3)直接将整个切片传入
	DB.Create(&studentList)

三、查询

3.1:查询单条记录

我们先来看一种比较简单的,使用Take()函数,查询一条记录:

  • 使用Take()函数,查询单条记录:

Take()函数将从数据库表中获取任何一条符合条件的记录。是根据数据库表中的主键或者默认排序规则来获取的。

	//定义一个结构体实体,用于存储数据库查询的返回的记录
	var student Student
	//使用gorm库中的方法,从数据库获取一条记录,映射到student变量中
	DB.Take(&student)
	fmt.Println(student)

注意:若上面已经执行了添加记录的语句,在执行查询语句时,需要把上面的增加语句注释掉,否则又会重复添加

  • First()Last()函数,返回查询结果集合的第一条、最后一条记录
DB.First(&student) 
// SELECT * FROM `students` ORDER BY `students`.`id` LIMIT 1
DB.Last(&student)  
// SELECT * FROM `students` ORDER BY `students`.`id` DESC LIMIT 1

如果没有指定排序顺序,默认是按主键顺序升序排序ordered by `students`.`id`.

  • 根据给定主键参数进行查询
	var stu Student
	DB.Take(&stu, 3)
	fmt.Println(stu)
	// SELECT * FROM `students` WHERE `students`.`id` = 3 LIMIT 1
  • 根据其他字段进行查询
	var stu Student
	DB.Take(&stu, "name = ?", "瑶瑶子")
	fmt.Println(stu)

注意,这里使用?作为占位符,原理是将用户输入进行转义后,再拼接。防止sql注入问题

3.2:查询多条记录

  • Find()查询数据库中所有与条件匹配的记录(以切片形式返回),如果没有,则返回空切片
var students []Student
	DB.Find(&students)
	for _, student := range students {
		fmt.Println(student)
	}
  • 根据主键进行查找
	var students []Student
	
	DB.Find(&students, []int{1, 3, 5, 6})
	DB.Find(&students, 1, 3, 5, 6) //和上面等价
	fmt.Println(students)
  • 根据其他条件查询
	var students []Student
	DB.Find(&students, "name in ?", []string{"瑶瑶子3号", "瑶瑶子6号"})

3.3:获取查询结果

  • 获取查询的记录数
	var students []Student
	DB.Find(&students)
	//核心代码如下行
	count := DB.Find(&students).RowsAffected
	fmt.Println(count)
  • 是否查询失败
	var students []Student

	err := DB.Find(&students).Error
	switch err {
	case gorm.ErrRecordNotFound:
		fmt.Println("没有找到")
	default:
		fmt.Println("sql错误")
	}

四、改

  • Save()进行单个记录的全字段更新
//1)先找到要修改的记录
	var student Student
	DB.Take(&student, 11)

	//2)对其字段进行修改
	student.Name = "是瑶瑶子啦"
	//3)使用sava,进行保存(数据库内相映射的记录更新)
	DB.Save(&student)
	// UPDATE `students` SET `name`='是瑶瑶子啦',`age`=19,`gender`email`='3051337060@qq.com' WHERE `id` = 11

注意:零值也会被更新(即将字段修改为零值,使用sava,其在数据库映射也会被修改)

  • Select()更新指定字段

可以看到,上面save()语句翻译成sql是进行全字段更新,即使只修改了一个。
使用select,则进行指定字段更新

	//1)先找到要修改的记录
	var student Student
	DB.Take(&student, 11)

	//2)对其字段进行修改
	student.Name = "是瑶瑶子啦"
	//3)使用sava,进行保存(数据库内相映射的记录更新)
	DB.Select("Name").Save(&student)
	// UPDATE `students` SET `name`='是瑶瑶子啦' WHERE `id` = 11
  • 批量更新
//1)让所有年龄为19的年龄全修改为20(使用了其他属性查询
	var students []Student
	DB.Find(&students, "age = ?", 19).Update("Age", 20)

	//2)将ID为1,2,3的年龄改为21(使用主键查询
	DB.Find(&students, 1, 2, 3).Update("Age", 21)
  • 使用结构体更新多字段(不会更新零值)
var students []Student

	DB.Find(&students, 1, 2, 3).Updates(Student{
		Name: "yyz",
		Age:  0, //结构体更新零值,不会进行修改
	})
	fmt.Println(students)
	//结果:[{1 yyz 21 70 0xc00022c940} {2 yyz 21 70 0xc00022c960} {3 yyz 21 70 0xc00022c980}]

  • 使用map更新多字段(会更新零值)
	DB.Model(&Student{}).Where("age = ?", 21).Updates(map[string]any{
		"age":  0,
		"name": "yyz2024",
	})
	//UPDATE `students` SET `age`=0,`name`='yyz2024' WHERE age = 21

五、删除

  • delete()根据主键进行删除
	DB.Delete(&student, 2)
	// DELETE FROM `students` WHERE `students`.`id` = 2
  • delete()根据主键批量删除
	DB.Delete(&student, 12, 13)
	// DELETE FROM `students` WHERE `students`.`id` IN (12,13)
  • delete()+其他条件,批量删除
DB.Delete(&Student{}, "name = ?", "是瑶瑶子啦")
//DELETE FROM `students` WHERE name = '是瑶瑶子啦'
  • delete()+where(其他条件)批量删除
//批量删除
	DB.Where("name = ?", "瑶瑶子").Delete(&Student{})
	// DELETE FROM `students` WHERE name = '瑶瑶子'

注意:

  • 警告 删除记录时,请确保主键字段有值,GORM 会通过主键去删除记录,如果主键为空,GORM 会删除该 model 的所有记录。
  • 如果一个 model 有 DeletedAt 字段,他将自动获得软删除的功能! 当调用 Delete 方法时, 记录不会真正的从数据库中被删除, 只会将DeletedAt 字段的值会被设置为当前时间

欢迎在评论区交流和留下你的想法和建议

如果对你有用,还请:💭评论+👍🏻点赞+⭐收藏+➕关注

在这里插入图片描述

  • Java岛冒险记【从小白到大佬之路】

  • GORM框架学习

  • Mysql从入门到精通

  • Go语言核心编程

  • LeetCode每日一题–进击大厂

  • 算法

  • C/C++

  • 数据结构

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

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

相关文章

M1 Mac配置JAVA环境

1、下载JDK 目前JDK有Oracle的JDK还有zulu的Open JDK可供选择&#xff0c;因为需要JAVA1.8所以下文以zulu的JDK为例。 Zulu官网&#xff1a;https://www.azul.com/downloads/?packagejdk 选择所需的JDK版本&#xff08;注意选择ARM架构&#xff09;> 下载.dmg包 > 安装 …

DAY 47 Ngnix优化与防盗链

Ngnix优化主要有两种&#xff0c;一种是配置上的优化&#xff0c;一种是内核上的优化 隐藏响应头中的版本号 方法一&#xff1a;curl命令 网页查看 隐藏版本信息 修改nginx的运行用户和组 方法一&#xff1a;在编译安装时&#xff0c;指定运行用户和组 [root nginx-1.12.2]#…

【英语】100个句子记完7000个雅思单词

其实主要的7000词其实是在主题归纳里面&#xff0c;不过过一遍100个句子也挺好的&#xff0c;反正也不多。 文章目录 Sentence 01Sentence 02Sentence 03Sentence 04Sentence 05Sentence 06Sentence 07Sentence 08Sentence 09Sentence 10Sentence 11Sentence 12Sentence 13Sent…

Linux常用的压缩、解压缩以及scp远程传输命令的使用

Linux常用的压缩、解压缩以及scp远程传输命令的使用 1.压缩命令2 解压命令3. 大文件压缩分割为多个压缩文件4. 远程传输命令scp4.1 将本地文件复制到远程主机目录4.2 将本地目录复制到远程主机目录4.3 将远程主机的文件复制到本机4.4 复制远程主机目录到本机 1.压缩命令 tar -…

Packet Tracer - 综合技能练习(配置新交换机的初始设置、SSH 和端口安全)

Packet Tracer - 综合技能练习 地址分配表 设备 接口 IP 地址 子网掩码 S1 VLAN 1 10.10.10.2 255.255.255.0 PC1 NIC 10.10.10.10 255.255.255.0 PC2 NIC 10.10.10.11 255.255.255.0 场景 网络管理员要求您配置新交换机。 在本练习中&#xff0c;您将使用一…

二分搜索算法通解框架

文章介绍了二分搜索最常见的几个场景的使用&#xff1a;寻找一个数、寻找左侧边界以及寻找右侧边界。阅读本文只需读者了解二分搜索的使用限制和基本原理即可。 我相信&#xff0c;友好的讨论交流会让彼此快速进步&#xff01;文章难免有疏漏之处&#xff0c;十分欢迎大家在评…

密码学【java】初探究加密方式之对称加密

文章目录 一 常见加密方式二 对称加密2.1 Cipher类简介2.2 Base算法2.3 补充&#xff1a;Byte&bit2.4 DES加密演示2.5 DES解密2.6 补充&#xff1a;对于IDEA控制台乱码的解决方法2.7 AES加密解密2.8 补充&#xff1a; toString()与new String ()用法区别2.9 加密模式2.9.1 …

MySQL学习笔记第六天

第06章多表查询 5. 7种SQL JOINS的实现 A是员工表&#xff0c;B是部门表。 5.7.1 代码实现 #8. UNION 和 UNION ALL的使用 # UNION&#xff1a;会执行去重操作 # UNION ALL:不会执行去重操作&#xff0c;效率优于前者&#xff0c;开发中优先使用 #结论&#xff1a;如果明确…

【Java入门合集】第二章Java语言基础(四——第二章结束)

【Java入门合集】第二章Java语言基础&#xff08;四——第二章结束&#xff09; 博主&#xff1a;命运之光 专栏&#xff1a;JAVA入门 学习目标 掌握变量、常量、表达式的概念&#xff0c;数据类型及变量的定义方法&#xff1b; 掌握常用运算符的使用&#xff1b; 掌握程序的顺…

【LeetCode股票买卖系列:188. 买卖股票的最佳时机 IV | 暴力递归=>记忆化搜索=>动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Hibernate(一)——入门

在之前经常用到操作数据库的框架是Mybatis或者Mybatis-plus。 Hibernate在項目中用过&#xff0c;但没有深入的了解过&#xff0c;所以这次趁着假期把这个框架了解一下。 目录 概念Hibernate和Mybatis的区别Hibernate使用依赖引入Hibernate配置文件XML配置文件详解properties文…

2023 年 五一杯 B 题过程 + 代码(第一问)

文章目录 第一题问题分析PageRank 算法&#xff08;可跳过&#xff09;PageRank 算法修正权重系数 结果各城市链出与链入链出 权重链入 权重 PageRank 算法结果代码 第一题 问题分析 从收货量、发货量、快递数量增长/减少趋势、相关性等多角度考虑&#xff0c;建立数学模型&…

如何使用git更新别人的代码

文章目录 如何使用git更新别人的代码问题说明省流问题示例操作步骤总结总结 如何使用git更新别人的代码 问题说明 当自己git clone别人的代码之后&#xff0c;代码一直停留到本地电脑上&#xff0c;而你就跑了一次程序就搁置了。 后来有一天你想再次运行该代码&#xff0c;但…

可观测性:你的应用健康吗?

一、需求来源 首先来看一下&#xff0c;整个需求的来源&#xff1a;当把应用迁移到 Kubernetes 之后&#xff0c;要如何去保障应用的健康与稳定呢&#xff1f;其实很简单&#xff0c;可以从两个方面来进行增强&#xff1a; 首先是提高应用的可观测性&#xff1b;第二是提高应…

Matplotlib 安装介绍

文章目录 安装步骤 Matplotlib 不止是一个数学绘图库&#xff0c;它也是可视化和分析工具中最流行之一。我们可用其制作简单的图表&#xff0c;如折线图和散点图。 安装步骤 先进入&#xff1a;python官网 跳转到界面&#xff1a; 录入并搜索 下载之前&#xff0c;看一下自…

嵌入式linux学习笔记--虚拟局域网组网方案分享,基于自组zerotier -planet 网络的方案

0. 前言 五一假期期间重新考虑了目前的组网环境&#xff0c;准备对目前的组网进行一个重新的划分。 目前有的资源 ① 两台 服务器&#xff0c;阿里云-深圳&#xff08;5M上行&#xff09;和腾讯云 广州&#xff08;3M上行&#xff09; ② 带动态公网IP的家庭宽带 &#xff08;…

伽马校正的前世今生

关于伽马校正的前因后果&#xff0c;在网上有不同版本的说法&#xff0c;由于年代久远的因素&#xff0c;导致原本很简单的事情越说越复杂。今天我们的目标就是抓住伽马的头&#xff0c;而不是摸一下伽马的尾巴。 一&#xff0c;鱼龙混杂的论调 1&#xff0c;CRT 显示器的物理…

系统集成项目管理工程师下午真题 计算题 及考点 汇总(更新中。。。)

文章目录 2022下半年广东卷 2022下半年广东卷 1、质量保证、质量控制。质量管理方面存在的问题&#xff0c;并给出正确的做法。判断下列选项的正误。 2、下表是一个软件项目在编码阶段各活动的计划和实际完成情况&#xff08;工作量&#xff0c;单位&#xff1a;人天&#xf…

Linux环境下的redis

一&#xff1a;安装与启动 1.下载redis安装包 2.解压&#xff1a;tar –xvf 文件名.tar.gz 3.安装 进入redis目录&#xff08;cd redis-x.x.x/)后&#xff0c;执行make install 命令 4.启动 进入src目录&#xff0c;执行redis-server 此时该界面无法再使用&#xff0c;需要…

Eureka 服务注册源码探秘——图解、源码级解析

&#x1f34a; Java学习&#xff1a;社区快速通道 &#x1f34a; 深入浅出RocketMQ设计思想&#xff1a;深入浅出RocketMQ设计思想 &#x1f34a; 绝对不一样的职场干货&#xff1a;大厂最佳实践经验指南 &#x1f4c6; 最近更新&#xff1a;2023年5月2日 &#x1f34a; 点…