Gorm -- 添加记录

news2025/1/11 3:49:40

文章目录

    • 添加单条记录
      • 直接添加模型对象
      • 赋予默认值方法一: gorm 标签
      • 赋予默认值方法二: 设置钩子方法(Hooks)
      • 指定字段插入
      • 插入时忽略某些字段
      • 插入时禁止使用钩子方法
    • 添加多条记录
      • 通过对象列表插入
      • 通过字典列表插入
      • 在字典中使用SQL内置函数
    • 关联插入
    • 取消关联插入
      • 取消指定关联插入
      • 取消所有关联插入
    • 冲突
      • 忽略冲突
      • 出现冲突修改行记录
        • 出现冲突时,修改字段为新的值
        • 出现冲突时,修改指定字段为新的值
        • 出现冲突时,修改指定字段内容
        • 使用内置函数

模型定义以及Gorm初始化请参考上一篇文章 https://mingvvv.blog.csdn.net/article/details/129026914

首先初始化连接池

db := cus_orm.MysqlConnection()

添加单条记录

直接添加模型对象

使用 Debug() 可以打印出 SQL 语句,开发时使用便于观察

user := &model.User{
	Name: "姓名",
}
// 添加一条
if err := db.Debug().Create(user).Error; err != nil {
	fmt.Println(err)
	return
}
-------------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`) VALUES ('姓名','',18,'这是一条默认描述',NULL,'2023-03-01 15:24:56','2023-03-01 15:24:56')

这里的对象中我们只给 Name 赋值,但是在实际执行的 SQL 中其他字段也有值,原因如下:

赋予默认值方法一: gorm 标签

在这里插入图片描述

赋予默认值方法二: 设置钩子方法(Hooks)

为结构体添加以下方法:
在这里插入图片描述
在模型对象创建的时候会依次调用这四个方法,执行循序为
BeforeSave => BeforeCreate => AfterCreate => AfterSave
因此我们可以在这些方法里面对对象做一些操作,如下,对CreateTime、UpdateTime、 UserDesc 做了简单的赋值

... ...
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
	u.CreateTime = time.Unix(time.Now().Unix(), 0) //初始化创建时间
	u.UpdateTime = time.Unix(time.Now().Unix(), 0) //初始化修改时间
	u.UserDesc = "这是一条默认描述"
	fmt.Println("BeforeCreate -- Auto Setting")
	return
}
... ...

指定字段插入

db.Debug().Select("Name").Create(&user)
db.Debug().Select("Name","UserDesc").Create(&user)
---------------------------
INSERT INTO `user` (`name`) VALUES ('姓名')
INSERT INTO `user` (`name`,`user_desc`) VALUES ('姓名','这是一条默认描述')

插入时忽略某些字段

忽略 UpdateTime

db.Debug().Omit("UpdateTime").Create(&user)
----------------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`id`) VALUES ('姓名','',18,'这是一条默认描述',NULL,'2023-03-01 15:50:59',539)

插入时禁止使用钩子方法

有的时候我们在保存时可能不需要狗子方法帮我们预处理数据,所以我们要禁用钩子方法
使用 Session(&gorm.Session{SkipHooks: true}),会发现我们上面在钩子方法没有执行

import "gorm.io/gorm"
db.Debug().Omit("UpdateTime").Session(&gorm.Session{SkipHooks: true}).Create(&user)
-------------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`) VALUES ('姓名','',18,'',NULL,'0000-00-00 00:00:00','0000-00-00 00:00:00')

添加多条记录

通过对象列表插入

CreateInBatches(&users, 100) 100表示每次插入的最大行数量。列表内的对象数量大于这个值时会分批次插入,每批次最大 100 行

users := []model.User{
{
		Name: "测试goper111",
	},
	{
		Name: "测试goper222",
	},
	{
		Name: "测试goper333",
	},
}
db.Debug().CreateInBatches(&users, 100)
--------------------------------------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`) VALUES 
('测试goper111','',18,'这是一条默认描述',NULL,'2023-03-01 16:04:18','2023-03-01 16:04:18'),
('测试goper222','',18,'这是一条默认描述',NULL,'2023-03-01 16:04:18','2023-03-01 16:04:18'),
('测试goper333','',18,'这是一条默认描述',NULL,'2023-03-01 16:04:18','2023-03-01 16:04:18')

通过字典列表插入

db.Model(&model.User{}).Debug().Create([]map[string]interface{}{
	{"Name": "姓名1", "Age": 18},
	{"Name": "姓名2", "Age": 20},
})
-------------------
INSERT INTO `user` (`age`,`name`) VALUES 
(18,'姓名1'),
(20,'姓名2')

在字典中使用SQL内置函数

使用 clause.Expr{SQL: “内置函数”, Vars: []interface{}{参数对象}}

import "gorm.io/gorm/clause"

db.Model(&model.User{}).Debug().Create([]map[string]interface{}{
	{"Name": clause.Expr{SQL: "Concat(?,?)", Vars: []interface{}{"姓名", "拼接"}}, "Age": 18},
})
----------------------------------------
INSERT INTO `user` (`age`,`name`) VALUES (18,Concat('姓名','拼接'))

还有一种方法也可以使用内置函数,但是需要提前自定义数据类型,比较繁琐。
实现过程可参考以下地址

https://gorm.io/docs/data_types.html#GormValuerInterface

关联插入

在结构体 User 中,我们最后两个字段关联了其他两个表。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果我们要插入的对象中,这两个元素不是空值,那么这两个结构体对应的表也会插入数据。
需要注意的是:
上图红框中我们制定了外键关系,即这两个表的 user_id 就是 user 表的外键,所以在插入时,这两个表的 user_id 会自动赋值为 user 表的 id

user2 := &model.User{
	Name: "姓名",
	UserRole: model.UserRole{
		RoleId: 1,
	},
	UserExtend: model.UserExtend{
		Gender: 1,
	},
}
db.Debug().Create(&user2)
--------------------------------------------
INSERT INTO `user_role` (`user_id`,`role_id`) VALUES (546,1) ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`)
INSERT INTO `user_extend` (`user_id`,`gender`) VALUES (546,1) ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`)
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`) VALUES ('姓名','',18,'这是一条默认描述',NULL,'2023-03-01 16:22:25','2023-03-01 16:22:25')

取消关联插入

取消指定关联插入

以下取消了 user_role 表的关联插入

user2 := &model.User{
	Name: "姓名",
	UserRole: model.UserRole{
		RoleId: 1,
	},
	UserExtend: model.UserExtend{
		Gender: 1,
	},
}
db.Debug().Omit("UserRole").Create(&user2)
-----------------------------------------
INSERT INTO `user_extend` (`user_id`,`gender`) VALUES (547,1) ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`)
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`) VALUES ('姓名','',18,'这是一条默认描述',NULL,'2023-03-01 16:29:09','2023-03-01 16:29:09')

取消所有关联插入

import "gorm.io/gorm/clause"
user2 := &model.User{
	Name: "姓名",
	UserRole: model.UserRole{
		RoleId: 1,
	},
	UserExtend: model.UserExtend{
		Gender: 1,
	},
}
db.Debug().Omit(clause.Associations).Create(&user2)
-----------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`) VALUES ('姓名','',18,'这是一条默认描述',NULL,'2023-03-01 16:29:09','2023-03-01 16:29:09')

冲突

我们在创建表的时候会创建一些唯一索引,这样的索引对应的列在表内是不允许存在重复数据的。
当我们插入了重复数据后,插入会报错。针对这种情况,我们可以忽略这些冲突或者将插入操作转变为修改操作。

忽略冲突

当出现冲突时,将id修改为id,实质上相当于什么也没做

user := &model.User{
	Id:        521,
	Name:      "姓名",
	JsonField: map[string]string{"test": "test"},
}
db.Debug().Clauses(clause.OnConflict{DoNothing: true}).Create(&user)
--------------------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`,`id`) 
VALUES ('姓名','',18,'这是一条默认描述','{"test":"test"}','2023-03-01 16:55:24','2023-03-01 16:55:24',521) 
ON DUPLICATE KEY UPDATE `id`=`id`

出现冲突修改行记录

出现冲突时,修改字段为新的值

user := &model.User{
	Id:        521,
	Name:      "姓名",
	JsonField: map[string]string{"test": "test"},
}
db.Debug().Clauses(clause.OnConflict{UpdateAll: true}).Create(&user)
---------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`,`id`) 
VALUES ('姓名','',18,'这是一条默认描述','{"test":"test"}','2023-03-01 17:20:13','2023-03-01 17:20:13',521) 
ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`infant_name`=VALUES(`infant_name`),`age`=VALUES(`age`),`user_desc`=VALUES(`user_desc`),`json_field`=VALUES(`json_field`),`create_time`=VALUES(`create_time`),`update_time`=VALUES(`update_time`)

出现冲突时,修改指定字段为新的值

db.Debug().Clauses(clause.OnConflict{
	DoUpdates: clause.AssignmentColumns([]string{"json_field", "name"}),
}).Create(&user)
---------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`,`id`) 
VALUES ('姓名','',18,'这是一条默认描述','{"test":"test"}','2023-03-01 17:17:35','2023-03-01 17:17:35',521) 
ON DUPLICATE KEY UPDATE `user_desc`=VALUES(`user_desc`),`name`=VALUES(`name`)

出现冲突时,修改指定字段内容

db.Debug().Clauses(clause.OnConflict{
	DoUpdates: clause.Assignments(map[string]interface{}{"user_desc": "冲突后做了修改"}),
}).Create(&user)
--------------------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`,`id`) 
VALUES ('姓名','',18,'这是一条默认描述','{"test":"test"}','2023-03-01 16:51:45','2023-03-01 16:51:45',521) 
ON DUPLICATE KEY UPDATE `user_desc`='冲突后做了修改'

使用内置函数

db.Debug().Clauses(clause.OnConflict{
	DoUpdates: clause.Assignments(map[string]interface{}{"user_desc": gorm.Expr("Concat('测试', '拼接')")}),
}).Create(&user)
--------------------------------------------------
INSERT INTO `user` (`name`,`infant_name`,`age`,`user_desc`,`json_field`,`create_time`,`update_time`,`id`) 
VALUES ('姓名','',18,'这是一条默认描述','{"test":"test"}','2023-03-01 17:15:17','2023-03-01 17:15:17',521) 
ON DUPLICATE KEY UPDATE `user_desc`=Concat('测试', '拼接')

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

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

相关文章

【Linux】工具(3)——gcc/g++

咱们继续进阶,接下来进入到Linux工具中gcc和g的学习在本章博客正式开始介绍之前,我们先要弄清楚程序是怎么翻译的:C语言程序环境一、什么是gcc/g📌gcc是一个c编译器, g是c编译器。我们根据代码的后缀名来判断用哪个编译…

NCRE计算机等级考试Python真题(十)

第十套试题1、数据库系统的核心是___________。A.数据库管理系统B.数据模型C.软件工具D.数据库正确答案: A2、下列叙述中正确的是___________。A.线性表链式存储结构的存储空间可以是连续的,也可以是不连续的B.线性表链式存储结构与顺序存储结构的存储空…

Stable Diffusion原理详解

Stable Diffusion原理详解 最近AI图像生成异常火爆,听说鹅厂都开始用AI图像生成做前期设定了,小厂更是直接用AI替代了原画师的岗位。这一张张丰富细腻、风格各异、以假乱真的AI生成图像,背后离不开Stable Diffusion算法。 Stable Diffusion…

大容量存储(涉及到的硬盘存取的原理)

磁盘的结构 我们简单分析一下,这里是计组的知识,大家可以自己多看些资料 柱面是基本单位 我们可以看到内圈的空间比外圈的要小,但是我们的每个磁道里的扇区是一样的,所以外圈的数据密度分布比内圈要更分散一些,这样就…

LeetCode 235. 二叉搜索树的最近公共祖先

LeetCode 235. 二叉搜索树的最近公共祖先 难度:middle\color{orange}{middle}middle 题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先…

解决pycharm中报ModuleNotFoundError: No module named ‘tensorflow‘错误

在pycharm中编写python程序时,遇到了报ModuleNotFoundError:no module named XXX的错误。以下是我的解决方法。 目录 一、错误现象 二、原因分析 三、解决方法 四、更多错误解决方法 一、错误现象 执行python程序时,报错,错误信息为Modu…

python字符串练习

python字符串练习 1.去掉字符串中所有的空格 s This is a demo print(s.replace( , )) 2.获取字符串中数字的个数 data input("请输入一些字符串:") a 0 for i in data:if i.isdigit():a a 1 print("数字个数:", a)3.将字母全部转换为…

Cypher中的聚合

深解Cypher中的聚合 值或计数的聚合要么从查询返回,要么用作多步查询下一部分的输入。查看数据模型 CALL db.schema.visualization() 查看图中节点的属性类型 CALL db.schema.notetypeproperties() 查看图中关系的属性类型 CALL db.schema.reltypeproperties() C…

普通二本,去过阿里外包,到现在年薪40W+的高级测试工程师,我的两年转行经历...

我是一个普通二本大学机械专业毕业,14年毕业,16年转行,目前做IT行业的软件测试已经有3年多,职位是高级软件测试工程师,坐标上海…我想现在我也有一点资格谈论关于转行这个话题;希望你在决定转行之前&#x…

爆品分析第4期 | 从周销12件到3700+件,这款收腰裤热度和口碑都爆了!

衣食住行,衣是排在第一位的,作为复购率最高的类目之一,服饰一直是TikTok上电商选品的风向标,是衡量电商发展情况的重要参考指标。随着疫情的结束和经济的日渐好转,消费者对服装类的需求上升。除了时装、T恤等日常消费的…

无损音乐格式:FLAC和ALAC

前言:我最近在弄苹果的airplay项目,发现airplay2对比airplay多了音质方面的增强。AAC和MP3接触过,但对FLAC和ALAC完全不了解,整理学习资料汇总成如下信息: AirPlay2 在2017年推出,在前一代AirPlay的基础上…

一篇文章搞性IPV6的原理和配置

本章对IPV6做了简单的介绍,并通过实验让读者了解IPV6地址和6TO4隧道的配置方法。 本章包含以下内容:  IPV6的概述 配置IPV6地址 配置6to4隧道  10.1 IPv6的概述 IPv6(Internet Protocol Version 6)是网络层协议…

MyBatis源码分析(一)MyBatis整体架构分析

文章目录一、为什么要用MyBatis1、原始JDBC的痛点2、Hibernate 和 JPA3、MyBatis的特点4、MyBatis整体架构5、MyBatis主要组件及其相互关系6、MyBatis源码的特点二、源码环境搭建未完待续一、为什么要用MyBatis 1、原始JDBC的痛点 在传统JDBC场景下,SQL 夹杂在Jav…

Databend 开源周报第 80 期

Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.com 。Whats New探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。Features & Improvements :…

Unity Asset Bundle学习 - 加载本地资源

Unity的 Asset Bundle 文档 https://docs.unity3d.com/cn/2019.4/Manual/AssetBundles-Workflow.html 第一次接触 直接按官方文档操作 下面接着按文档走流程 构建AssetBundle 此脚本将在 Assets 菜单底部创建一个名为 Build AssetBundles 的菜单项,该菜单项将执行与…

STM32学习笔记-DMA

文章目录一、功能框图通道选择仲裁器FIFO1. **FIFO**: First in First out2. FIFO作用:端口二、DMA模式配置1. 传输模式2. 源地址和目标地址3. 流控制器4. 循环模式5. 传输类型6. 直接模式7. 双缓冲模式8.DMA中断事件三、程序设计1. DMA初始化结构体DMA(Direct Memo…

20 | k8s v1.20集群搭建master和node

1 单节点master 1.1 服务器整体规划 1.2 单Master架构图 1.3 初始化配置 1.3.1 关闭防火墙 systemctl stop firewalld systemctl disable firewalld1.3.2 关闭selinux sed -i s/enforcing/disabled/ /etc/selinux/config # 永久 setenforce 0 # 临时 1.3.3 关闭swap …

tiktok小店如何找到美妆爆品?(内附2月tiktok数据分析)

根据相关数据统计,2023年来全球美妆个护零售总额稳步增长。随着全球化加剧,越来越多的美妆个护品牌选择出海,寻找新的增长和变现机会。Tiktok的快速发展给这些美妆个护品牌提供了新的可能,打通了出海的新思路。同时对于出海的小店…

LeetCode 2373. 矩阵中的局部最大值

LeetCode 2373. 矩阵中的局部最大值 难度:easy\color{Green}{easy}easy 题目描述 给你一个大小为 nxnn x nnxn 的整数矩阵 gridgridgrid 。 生成一个大小为 (n−2)x(n−2)(n - 2) x (n - 2)(n−2)x(n−2) 的整数矩阵 maxLocalmaxLocalmaxLocal ,并满足…

解决Ubuntu虚拟机不能复制粘贴

安装虚拟机的时候就有点不顺,在填写用户名和密码的时候键盘敲不上字,重新又安装了几次才行,安装成功后发现不能复制粘贴主机的内容,这肯定不行啊,找解决方案,网上也有很多,有如下:重…