gorm 一对多关系 以及预加载的用法

简介: gorm 一对多关系 以及预加载的用法

一对多关系的介绍

这里女神表里面有多个舔狗,就是一对多has many关系

并且舔狗表里面包含Info信息表,是has one关系

type GirlGOD struct {
  gorm.Model
  Name string
  Dog  []Dog
}
type Dog struct {
  gorm.Model
  Name      string
  GirlGodID uint
  Info      Info
}
type Info struct {
  gorm.Model
  Age   int
  Money int
  DogID uint
}
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
  info1 := Info{
    Age:   1,
    Money: 1,
  }
  info2 := Info{
    Age:   2,
    Money: 2,
  }
  dog1 := Dog{
    Name: "dog1",
    Info: info1,
  }
  dog2 := Dog{
    Name: "dog2",
    Info: info2,
  }
  girl1 := GirlGOD{
    Name: "girl1",
    Dogs:  []Dog{dog1},
  }
  girl2 := GirlGOD{
    Name: "girl2",
    Dogs:  []Dog{dog2},
  }
  db.Debug().Create(&girl1)
  db.Debug().Create(&girl2)
}

预加载

Preload预加载

Preload 在一个单独查询中加载关联数据。

不使用预加载

查不出关联的舔狗的信息

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
  var girls []GirlGOD
  db.Debug().Find(&girls)
  fmt.Println(girls)
  for _, v := range girls {
    for i := range v.Dogs {
      fmt.Println(v.Name, v.Dogs[i].Name, v.Dogs[i].Info.Money)
    }
  }
}
2022/05/15 22:53:29 C:/Users/68725/Desktop/leetcode/main.go:32
[42.024ms] [rows:2] SELECT * FROM `girl_gods` WHERE `girl_gods`.`deleted_at` IS NULL
[{{1 2022-05-15 22:43:14.714 +0800 CST 2022-05-15 22:43:14.714 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl1 []} {{2 2022-05-15 22:43:14.756 +0800 CST 2022-05-15 22:43:14.756 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl2 []}]

使用预加载

查出与girlgod关联的dog表的信息,但是与dog表关联的info表信息没有

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
  var girls []GirlGOD
  db.Debug().Preload("Dogs").Find(&girls)
  fmt.Println(girls)
  for _, v := range girls {
    for i := range v.Dogs {
      fmt.Println(v.Name, v.Dogs[i].Name, v.Dogs[i].Info.Money)
    }
  }
}
2022/05/15 22:54:22 C:/Users/68725/Desktop/leetcode/main.go:32
[0.651ms] [rows:2] SELECT * FROM `dogs` WHERE `dogs`.`girl_god_id` IN (1,2) AND `dogs`.`deleted_at` IS NULL
2022/05/15 22:54:22 C:/Users/68725/Desktop/leetcode/main.go:32
[49.459ms] [rows:2] SELECT * FROM `girl_gods` WHERE `girl_gods`.`deleted_at` IS NULL
[{{1 2022-05-15 22:43:14.714 +0800 CST 2022-05-15 22:43:14.714 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl1 [{{1 2022-05-15 22:43:14.752 +0800 CST 2022-05-15 22:43:14.752 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 1 {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}}]} {{2 2022-05-15 22:43:14.756 +0800 CST 2022-05-15 22:43:14.756 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl2 [{{2 2022-05-15 22:43:14.757 +0800 CST 2022-05-15 22:43:14.757 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog2 2 {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}}]}]
girl1 dog1 0
girl2 dog2 0
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
  var girls []GirlGOD
  db.Debug().Preload("Dogs.Info").Preload("Dogs").Find(&girls)
  fmt.Println(girls)
  for _, v := range girls {
    for i := range v.Dogs {
      fmt.Println(v.Name, v.Dogs[i].Name, v.Dogs[i].Info.Money)
    }
  }
}

使用链式预加载

将与girlgod关联的dog表的信息,dog表与info表关联的信息都查出来

2022/05/15 22:55:26 C:/Users/68725/Desktop/leetcode/main.go:32
[0.000ms] [rows:2] SELECT * FROM `infos` WHERE `infos`.`dog_id` IN (1,2) AND `infos`.`deleted_at` IS NULL
2022/05/15 22:55:26 C:/Users/68725/Desktop/leetcode/main.go:32
[1.531ms] [rows:2] SELECT * FROM `dogs` WHERE `dogs`.`girl_god_id` IN (1,2) AND `dogs`.`deleted_at` IS NULL
2022/05/15 22:55:26 C:/Users/68725/Desktop/leetcode/main.go:32
[44.470ms] [rows:2] SELECT * FROM `girl_gods` WHERE `girl_gods`.`deleted_at` IS NULL
[{{1 2022-05-15 22:43:14.714 +0800 CST 2022-05-15 22:43:14.714 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl1 [{{1 2022-05-15 22:43:14.752 +0800 CST 2022-05-15 22:43:14.752 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 1 {{1 2022-05-15 22:43:14.753 +0800 CST 2022-05-15 22:43:14.753 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} 1 1 1}}]} {{2 2022-05-15 22:43:14.756 +0800 CST 2022-05-15 22:43:14.756 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl2 [{{2 2022-05-15 22:43:14.757 +0800 CST 2022-05-15 22:43:14.757 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog2 2 {{2 2022-05-15 22:43:14.757 +0800 CST 2022-05-15 22:43:14.757 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} 2 2 2}}]}]
girl1 dog1 1
girl2 dog2 2

条件预加载

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
  var girls []GirlGOD
  db.Debug().Preload("Dogs.Info", "money>0").Preload("Dogs", "name=?", "dog2").Find(&girls)
  fmt.Println(girls)
  for _, v := range girls {
    for i := range v.Dogs {
      fmt.Println(v.Name, v.Dogs[i].Name, v.Dogs[i].Info.Money)
    }
  }
}
2022/05/15 22:56:47 C:/Users/68725/Desktop/leetcode/main.go:32
[1.509ms] [rows:1] SELECT * FROM `infos` WHERE `infos`.`dog_id` = 2 AND money>0 AND `infos`.`deleted_at` IS NULL
2022/05/15 22:56:47 C:/Users/68725/Desktop/leetcode/main.go:32
[1.509ms] [rows:1] SELECT * FROM `dogs` WHERE `dogs`.`girl_god_id` IN (1,2) AND name='dog2' AND `dogs`.`deleted_at` IS NULL
2022/05/15 22:56:47 C:/Users/68725/Desktop/leetcode/main.go:32
[42.171ms] [rows:2] SELECT * FROM `girl_gods` WHERE `girl_gods`.`deleted_at` IS NULL
[{{1 2022-05-15 22:43:14.714 +0800 CST 2022-05-15 22:43:14.714 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl1 []} {{2 2022-05-15 22:43:14.756 +0800 CST 2022-05-15 22:43:14.756 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl2 [{{2 2022-05-15 22:43:14.757 +0800 CST 2022-05-15 22:43:14.757 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog2 2 {{2 2022-05-15 22:43:14.757 +0800 CST 2022-05-15 22:43:14.757 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} 2 2 2}}]}]
girl2 dog2 2

Joins 预加载

Join Preload 会使用 inner join 加载关联数据

注意 Join Preload 适用于一对一的关系,例如: has one, belongs to

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
  var girls []GirlGOD
  db.Debug().Preload("Dogs", func(db *gorm.DB) *gorm.DB {
    return db.Joins("Info").Where("money>1")
  }).Find(&girls)
  fmt.Println(girls)
}
SELECT `dogs`.`id`,
       `dogs`.`created_at`,
       `dogs`.`updated_at`,
       `dogs`.`deleted_at`,
       `dogs`.`name`,
       `dogs`.`girl_god_id`,
       `Info`.`id`         AS `Info__id`,
       `Info`.`created_at` AS `Info__created_at`,
       `Info`.`updated_at` AS `Info__updated_at`,
       `Info`.`deleted_at` AS `Info__deleted_at`,
       `Info`.`age`        AS `Info__age`,
       `Info`.`money`      AS `Info__money`,
       `Info`.`dog_id`     AS `Info__dog_id`
FROM `dogs`
         LEFT JOIN `infos` `Info` ON `dogs`.`id` = `Info`.`dog_id` AND `Info`.`deleted_at` IS NULL
WHERE money > 1
  AND `dogs`.`girl_god_id` IN (1, 2)
  AND `dogs`.`deleted_at` IS NULL


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
Java 数据库 Spring
Spring事务的传播机制(行为、特性)
Spring事务的传播机制(行为、特性)
801 0
|
SQL Go 数据库
Gorm使用教程:掌握高级查询的技巧。
以上就是我们今天的旅程中所会遇到的一些有趣的Gorm查询技巧。学习这些技巧像是学着驾驶一辆全新的巴士,只要你掌握了这些,你可以在数据库的海洋中自由驾驶,轻松地转向,畅游其中。祝你在Gorm的世界中探索愉快!
379 36
|
机器学习/深度学习 数据可视化 算法
|
人工智能 中间件 Go
Go 项目实战:全局异常处理
在 Go 项目中,异常处理是保障程序稳定性的关键。本文介绍 Go 的错误处理机制与 panic 恢复方法,并探讨如何实现全局异常处理中间件,以统一捕获和处理运行时错误,提升代码可维护性与健壮性。
535 7
|
消息中间件 数据库
TCC(Try-Confirm-Cancel)
【6月更文挑战第5天】
1465 3
|
Kubernetes 负载均衡 调度
【Docker 专栏】Docker Swarm 与 Kubernetes 的选型指南
【5月更文挑战第8天】Docker Swarm 和 Kubernetes 是两大容器编排工具,各有优势。Docker Swarm 简单易用,适合小到中型规模,与 Docker 生态系统集成紧密;而 Kubernetes 功能强大,扩展性好,适用于大规模、复杂场景。选择时需考虑团队技术能力、应用需求及现有技术栈。Kubernetes 学习曲线较陡,Docker Swarm 则较平缓。
1237 7
【Docker 专栏】Docker Swarm 与 Kubernetes 的选型指南
|
Kubernetes 监控 Perl
在k8S中,自动扩容机制是什么?
在k8S中,自动扩容机制是什么?
|
存储 监控 物联网
【Clickhouse 探秘】Clickhouse 投影技术到底能做什么?怎么实现的?
ClickHouse 投影是一种数据结构,用于提高特定查询模式下的性能。通过预处理数据,投影可以显著减少查询的执行时间,特别是在复杂的聚合和排序查询中。投影自动与基础表数据保持同步,支持多投影,适用于实时分析、用户行为分析、日志分析等场景。虽然投影能显著提升查询性能,但也会增加存储开销和写入性能的影响。
724 0
|
网络协议 安全 调度
通过memberlist库实现gossip管理集群以及集群数据交互
通过memberlist库实现gossip管理集群以及集群数据交互
399 5
|
Linux 网络安全 数据安全/隐私保护

热门文章

最新文章