Golang Gorm 一对多查询 preload预加载

这篇具有很好参考价值的文章主要介绍了Golang Gorm 一对多查询 preload预加载。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

预加载示例  preload + find/take


Golang Gorm 一对多查询 preload预加载,Golang Gorm,golang

 GORM允许使用 Preload通过多个SQL中来直接加载关系, 例如:

type User struct {
  gorm.Model
  Username string
  Orders   []Order
}

type Order struct {
  gorm.Model
  UserID uint
  Price  float64
}

// 查找 user 时预加载相关 Order
db.Preload("Orders").Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4);



// 预加载Orders、Profile、Role多个关联属性  ps: 预加载字段,必须是User的属性
db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users)

// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many
// SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one
// SELECT * FROM roles WHERE id IN (4,5,6); // belongs to
	var u []User
	db.Debug().Preload("Articles").Find(&u)
	fmt.Println(u)

[1.486ms] [rows:7] SELECT * FROM `article` WHERE `article`.`user_id` IN (1,2,3)

[2.644ms] [rows:3] SELECT * FROM `user`
[{1 lucas [{1 golang 1} {2 k8s 1}]} {2 yanzi [{3 golang 2} {4 k8s 2}]} {3 test [{5 redis 3} {6 cherry 3} {7 marry 3}]}]
	var u User
	db.Debug().Where("name = ?", "lucas").Find(&u)
	fmt.Printf("%#v\n", u)

	db.Debug().Preload("Articles").Find(&u)
	fmt.Printf("%#v\n", u)

	var a Article
	db.Debug().Take(&a, 8)
	fmt.Printf("%#v\n", a)

	db.Debug().Preload("User").Find(&a)
	fmt.Printf("%#v\n", a)

[1.306ms] [rows:4] SELECT * FROM `article` WHERE `article`.`user_id` = 1

[3.628ms] [rows:1] SELECT * FROM `user` WHERE `user`.`id` = 1
main.User{ID:1, Name:"lucas", Articles:[]main.Article{main.Article{ID:1, Title:"k8s", UserID:1, User:main.User{ID:0, Name:"", Arti
cles:[]main.Article(nil)}}, main.Article{ID:2, Title:"golang", UserID:1, User:main.User{ID:0, Name:"", Articles:[]main.Article(nil
)}}, main.Article{ID:9, Title:"c", UserID:1, User:main.User{ID:0, Name:"", Articles:[]main.Article(nil)}}, main.Article{ID:10, Tit
le:"ruby", UserID:1, User:main.User{ID:0, Name:"", Articles:[]main.Article(nil)}}}}


[1.667ms] [rows:1] SELECT * FROM `article` WHERE `article`.`id` = 8 LIMIT 1
main.Article{ID:8, Title:"c++", UserID:3, User:main.User{ID:0, Name:"", Articles:[]main.Article(nil)}}


[1.124ms] [rows:1] SELECT * FROM `user` WHERE `user`.`id` = 3


[3.090ms] [rows:1] SELECT * FROM `article` WHERE `article`.`id` = 8
main.Article{ID:8, Title:"c++", UserID:3, User:main.User{ID:3, Name:"jerry", Articles:[]main.Article(nil)}}

preload的原理


其实很简单,你要preload user表的数据,gorm就提前把这张表全部取出来,然后再执行FirstFind这样的方法去查询主数据,最后把两种数据通过外键关联一一对应起来。

其实preload也就是做了两次查询。

	var u User
	db.Debug().Preload("Articles").Take(&u, "name = ?", "test")
	fmt.Println(u)


[2.007ms] [rows:3] SELECT * FROM `article` WHERE `article`.`user_id` = 3

[3.056ms] [rows:1] SELECT * FROM `user` WHERE name = 'test' LIMIT 1
{3 test [{5 redis 3} {6 cherry 3} {7 marry 3}]}

带条件预加载  只想展示某些


 Golang Gorm 一对多查询 preload预加载,Golang Gorm,golang

	var u User
	db.Debug().Where("name = ?", "lucas").Find(&u)

	db.Debug().Preload("Articles", "id = ?", 2).Find(&u)
	fmt.Println(u)

{1 lucas [{2 golang 1 {0  []}}]}

嵌套预加载


Golang Gorm 一对多查询 preload预加载,Golang Gorm,golang

	var a Article
	db.Debug().Take(&a, 8)
	db.Debug().Preload("User.Articles").Find(&a)
	fmt.Printf("%#v\n", a)

[4.840ms] [rows:1] SELECT * FROM `article` WHERE `article`.`id` = 8
main.Article{ID:8, Title:"c++", UserID:3, User:main.User{ID:3, Name:"jerry", Articles:[]main.Article{main.Article{ID:8, Title:"c++", UserID:3, User:m
ain.User{ID:0, Name:"", Articles:[]main.Article(nil)}}}}}

级联删除


Golang Gorm 一对多查询 preload预加载,Golang Gorm,golang

	var u User
	
	db.Debug().Where("name = ?", "lisa").Find(&u)
	db.Debug().Select("Articles").Delete(&u)

[0.748ms] [rows:1] SELECT * FROM `user` WHERE name = 'lisa'
[2.106ms] [rows:1] DELETE FROM `article` WHERE `article`.`user_id` = 4
[6.887ms] [rows:1] DELETE FROM `user` WHERE `user`.`id` = 4

清除外键关系   Association + Delete、Clean


Golang Gorm 一对多查询 preload预加载,Golang Gorm,golang

 有了preload,那么user就可以通过.点出来。

	db.Debug().Preload("Articles").Take(&u, 1
	)
	fmt.Println(u)


[4.167ms] [rows:1] SELECT * FROM `user` WHERE `user`.`id` = 1 LIMIT 1
{1 lucas [{1 k8s 1 {0  []}} {2 golang 1 {0  []}} {9 c 1 {0  []}} {10 ruby 1 {0  []}}]}
	var u User
	db.Take(&u, 2)
	db.Model(&u).Association("Articles").Find(&u.Articles)
	db.Debug().Model(&u).Association("Articles").Delete(&u.Articles)

[4.128ms] [rows:2] UPDATE `article` SET `user_id`=NULL WHERE `article`.`user_id` = 2 AND `article`.`id` IN (3,7)

mysql> select * from user;
+----+-------+
| id | name  |
+----+-------+
|  2 | yanzi |
|  3 | lucas |
|  4 | yanzi |
+----+-------+
3 rows in set (0.00 sec)

mysql> select * from article;
+----+--------+---------+
| id | title  | user_id |
+----+--------+---------+
|  1 | golang |    NULL |
|  2 | k8s    |    NULL |
|  3 | c#     |       2 |
|  4 | golang |       3 |
|  5 | k8s    |       3 |
|  6 | c#     |       4 |
|  7 | oracle |       2 |
+----+--------+---------+
7 rows in set (0.00 sec)

#修改之后

mysql> select * from user;
+----+-------+
| id | name  |
+----+-------+
|  2 | yanzi |
|  3 | lucas |
|  4 | yanzi |
+----+-------+

mysql> select * from article;
+----+--------+---------+
| id | title  | user_id |
+----+--------+---------+
|  1 | golang |    NULL |
|  2 | k8s    |    NULL |
|  3 | c#     |    NULL |
|  4 | golang |       3 |
|  5 | k8s    |       3 |
|  6 | c#     |       4 |
|  7 | oracle |    NULL |
+----+--------+---------+

  清空关联关系示例:先清空关联关系,再删除文章来源地址https://www.toymoban.com/news/detail-674679.html

	var u User
	db.Take(&u, 1)
	db.Debug().Model(&u).Association("Articles").Clear()

[11.177ms] [rows:2] UPDATE `article` SET `user_id`=NULL WHERE `article`.`user_id` = 1



mysql> select * from user;
+----+-------+
| id | name  |
+----+-------+
|  1 | lucas |
|  2 | yanzi |
|  3 | lucas |
|  4 | yanzi |
+----+-------+

mysql> select * from article;
+----+--------+---------+
| id | title  | user_id |
+----+--------+---------+
|  1 | golang |    NULL |
|  2 | k8s    |    NULL |
|  3 | c#     |       2 |
|  4 | golang |       3 |
|  5 | k8s    |       3 |
|  6 | c#     |       4 |
|  7 | oracle |       2 |
+----+--------+---------+


db.Debug().Delete(&u)
[9.960ms] [rows:1] DELETE FROM `user` WHERE `user`.`id` = 1


mysql> select * from user;
+----+-------+
| id | name  |
+----+-------+
|  2 | yanzi |
|  3 | lucas |
|  4 | yanzi |
+----+-------+

mysql> select * from article;
+----+--------+---------+
| id | title  | user_id |
+----+--------+---------+
|  1 | golang |    NULL |
|  2 | k8s    |    NULL |
|  3 | c#     |       2 |
|  4 | golang |       3 |
|  5 | k8s    |       3 |
|  6 | c#     |       4 |
|  7 | oracle |       2 |
+----+--------+---------+

到了这里,关于Golang Gorm 一对多查询 preload预加载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Golang通过Gorm操作Mysql时遇到的datetime时区问题

    golang使用Gorm操作MySQL,MySQL中数据类型是datetime,Golang中用的是time.now。 但是会导致存储的时间与北京时间有8h误差, 显然是没有初始化时区导致。 参考我自己之前写过的一篇总结——Mysql中多种日期类型——DATETIME、TIMESTAMP、TIME、YEAR、DATE的区分 datetime是给什么就存什么,

    2024年01月20日
    浏览(40)
  • Golang+Gorm库使用踩坑——未标识primarykey导致创建后无法返回修改

    做毕设ing,基本的增删改查。 这里是一个需要增的地方,代码如下: 我在外层调用时候,是需要返回新增记录的ID。但是无法符合预期。通过打印发现,我这里返回的id就是0。 翻阅之前写的一个正确样例,对比发现 区别在于,我这里没有去指定主键。 根据官方文档,其de

    2024年01月19日
    浏览(40)
  • golang-gin-mysql转gorm-struct--gen-model

    背景 :python-django项目用go-gin重构,数据库已存在,gin中使用gorm 所以需要工具将mysql数据库中的表结构转到orm的model中。 前提:因为国内访问github需要稳定的代理 Goproxy.cn  推荐这个 1.在项目路径中下载gen-model模块  go get -u github.com/DaoYoung/gen-model # GOBIN 目录下会有一个gen-model

    2024年02月09日
    浏览(37)
  • [Golang实战] gorm中使用Raw()和 Exec() 两种方式操作sql原生语句的特点和区别

    当我在gorm中使用原生sql操作数据库时,时常用raw() 和 exec() ,有时候经常遇到数据插不进去或者 数据帮i当不到结构体,原来是 这两个方法有不同的用处和特点 个人理解: 需要查询数据 映射到结构体时使用 官方理解: DB.Raw() 方法用于执行原始 SQL 查询语句或可执行的命令。

    2024年02月13日
    浏览(50)
  • golang使用os/exec库查询进程

    本文主要介绍如何使用os/exec库查询进程。 输出: 上述代码逻辑会获取到当前系统中所有运行的进程,但如果只需要获取制定进程信息呢,就需要针对进程进行过滤。 第一种方式: 输出: 第二种方式: 输出:

    2024年02月11日
    浏览(35)
  • 【从零单排Golang】第十五话:用sync.Once实现懒加载的用法和坑点

    在使用Golang做后端开发的工程中,我们通常需要声明一些一些配置类或服务单例等在业务逻辑层面较为底层的实例。为了节省内存或是冷启动开销,我们通常采用lazy-load懒加载的方式去初始化这些实例。初始化单例这个行为是一个非常经典的并发处理的案例,比如在java当中,

    2024年02月10日
    浏览(38)
  • 视频预加载(preload)实现

    如果网页中只有一个视频文件,您可能会使用 video 标签的 preload 属性来提示浏览器预加载的信息或内容量。但这意味着 Media Source Extensions(MSE)与 preload 将不兼容。 资源的获取将仅在HTML文档初始加载和解析完成后启动(例如, DOMContentLoaded 事件的触发),而 window.onload 事件

    2024年02月03日
    浏览(33)
  • 智能合约模拟调用的具体应用:在golang中查询uniswap v3智能合约上某代币的价格

    合约的方法如果是public view的,那么通过golang代码可以直接调用,步骤大致为: 1、使用合约的ABI生成.go文件接口 2、使用以太坊节点链接初始化以太坊客户端; 3、以以太坊客户端和uniswap合约地址为参数,实例化uniswap合约 4、直接调用uniswap的“查询价格”的方法,传入代币地

    2024年02月07日
    浏览(91)
  • webpack配置preload和prefetch预加载技术

    我们前面已经做了代码分割,同时会使用 import 动态导入语法来进行代码按需加载(我们也叫 懒加载 ,比如路由懒加载就是这样实现的)。 但是加载速度还不够好,比如:是用户 点击按钮时 才加载这个资源的, 如果资源体积很大,那么用户会感觉到明显卡顿效果 。 要优化

    2024年02月09日
    浏览(49)
  • electron学习-03preload 预加载-主进程 和 渲染进程之间通信

    主进程 是有着完全操作系统访问权限的 Node.js 环境; 渲染进程 默认跑在网页页面上。 渲染进程不能直接访问 Node.js 接口;主进程访不能直接访问 DOM。 预加载 脚本 运行在 具有 HTML DOM 和 Node.js、Electron API 的有限子集访问权限的环境中 预加载脚本: 将 Electron 的不同类型的进

    2023年04月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包