运维八一 运维八一
首页
运维杂记
编程浅尝
周积跬步
专栏
生活
关于
收藏
  • 分类
  • 标签
  • 归档
Source (opens new window)

运维八一

运维,运维!
首页
运维杂记
编程浅尝
周积跬步
专栏
生活
关于
收藏
  • 分类
  • 标签
  • 归档
Source (opens new window)
  • Go

    • 前言

    • Go基础知识

    • Go基本语法

    • 实战项目:简单web服务

    • 基本数据类型

    • 内置运算符

    • 分支和循环

    • 函数 function

    • 结构体 struct

    • 方法 method

    • 实战项目:跟踪函数调用链

    • 接口 interface

    • 并发 concurrency

    • 指针

    • 实战项目:实现轻量级线程池

    • 实战项目:实现TCP服务器

    • go常用包

    • Gin框架

      • gin入门
      • gin工作流程
      • gin中间件
      • gin路由
      • gin请求
      • 数据绑定和校验
      • 响应返回
      • 路由分发
      • Cookie和Session
      • gin项目结构
      • GORM入门
      • 一对多关联查询
        • 1 一对多入门
          • 1.1 has many介绍
          • 1.2 外键
          • 1.3 外键关联
        • 2. 创建一对多表
          • 2.1 表结构定义
          • 2.2 一对多 Association
          • 2.3 一对多 Preload
    • go随记

  • Python

  • Shell

  • Java

  • Vue

  • 前端

  • 编程浅尝
  • Go
  • Gin框架
lyndon
2022-07-11
目录

一对多关联查询

文档参考 (opens new window)

# 1 一对多入门

# 1.1 has many介绍

has many 关联就是创建和另一个模型的一对多关系。不同于 has one,拥有者可以有零或多个关联模型。

例如, 例如每一个用户都拥有多张信用卡,这样就是生活中一个简单的一对多关系。

image-20220711000509295

// 用户有多张信用卡,UserID 是外键
type User struct {
  gorm.Model
  CreditCards []CreditCard
}
type CreditCard struct {
  gorm.Model
  Number  string
  UserID  uint   // 默认会在 CreditCard 表中生成 UserID 字段作为 与User表关联的外键ID
}
1
2
3
4
5
6
7
8
9
10

# 1.2 外键

为了定义一对多关系, 外键是必须存在的,默认外键的名字是 所有者类型的名字加上它的主键 (UserId) 。就像上面的例子,为了定义一个属于 User 的模型,外键就应该为 UserID 。

使用其他的字段名作为外键, 可以通过 foreignkey 来定制它。

type User struct {
  gorm.Model
  // foreignkey:UserRefer 可以自己指定外键关联字段名为:UserRefer
  // 默认外键字段名是 UserId,你也可以自己修改
  CreditCards []CreditCard `gorm:"foreignkey:UserRefer"`
}
type CreditCard struct {
  gorm.Model
  Number   string
  UserRefer uint
}
1
2
3
4
5
6
7
8
9
10
11

# 1.3 外键关联

GORM 通常使用所有者的主键作为外键的值, 在上面的例子中,它就是 User 的 ID 。

当你分配信用卡给一个用户, GORM 将保存用户 ID 到信用卡表的 UserID 字段中。

你能通过 association_foreignkey 来改变它。

type User struct {
  gorm.Model
  MemberNumber string
  // 默认CreditCard会使用User表的Id作为外键,association_foreignkey:MemberNumber 指定使用 MemberNumber 作为外键关联
  CreditCards []CreditCard `gorm:"foreignkey:UserMemberNumber;association_foreignkey:MemberNumber"`
}

type CreditCard struct {
  gorm.Model
  Number      string
  UserMemberNumber  string
}
1
2
3
4
5
6
7
8
9
10
11
12

# 2. 创建一对多表

文档参考 (opens new window)

# 2.1 表结构定义

重写外键、外键约束

package main
import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

/*
constraint:OnUpdate:CASCADE 【当User表更新,也会同步给CreditCards】 // 外键约束
OnDelete:SET NULL 【当User中数据被删除时,CreditCard关联设置为 NULL,不删除记录】
*/

type User struct {
	gorm.Model
	Username   string    `json:"username" gorm:"column:username"`
	CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

type CreditCard struct {
	gorm.Model
	Number string
	UserID uint
}

func main() {
	// 0、连接数据库
	dsn := "root:1@tcp(127.0.0.1:3306)/test_db?
	charset=utf8mb4&parseTime=True&loc=Local"
	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	// 创建表结构
	db.AutoMigrate(User{}, CreditCard{})
	
    // 1、创建一对多
	user := User{
		Username: "zhangsan",
		CreditCards: []CreditCard{
			{Number: "0001"},
			{Number: "0002"},
		},
	}
	db.Create(&user)

    // 2、为已存在用户添加信用卡
	u := User{Username: "zhangsan"}
	db.First(&u)
	//fmt.Println(u.Username)
	db.Model(&u).Association("CreditCards").Append([]CreditCard{
		{Number: "0003"},
	})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

创建结果说明

我们没有指定 foreignkey,所以会与 UserID字段自动建立外键关联关系。

image-20220711001315349

# 2.2 一对多 Association

使用 Association 方法, 需要把 User 查询好, 然后根据 User 定义中指定的 AssociationForeignKey 去查找 CreditCard。

package main
import (
	"encoding/json"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

/*
constraint:OnUpdate:CASCADE 【当User表更新,也会同步给CreditCards】
OnDelete:SET NULL 【当User中数据被删除时,CreditCard关联设置为 NULL,不删除记录】
*/

type User struct {
	gorm.Model
	Username   string    `json:"username" gorm:"column:username"`
	CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`

type CreditCard struct {
	gorm.Model
	Number string
	UserID uint
}
    
func main() {
	// 0、连接数据库
	dsn := "root:1@tcp(127.0.0.1:3306)/test_db?
	charset=utf8mb4&parseTime=True&loc=Local"
	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})

    // 1、查找 用户名为 zhangsan 的所有信用卡信息
	u := User{Username: "zhangsan"}  // Association必须要先查出User才能关联查询对应的CreditCard
	db.First(&u)
	err := db.Model(&u).Association("CreditCards").Find(&u.CreditCards)
	if err != nil {
		fmt.Println(err)
	}
	strUser, _ := json.Marshal(&u)
	fmt.Println(string(strUser))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

打印结果如下:

{
  "ID":1,
  "username":"zhangsan",
  "CreditCards":[
   {
      "ID":1,
      "Number":"0001",
      "UserID":1
   },
...
 ]
}
1
2
3
4
5
6
7
8
9
10
11
12

# 2.3 一对多 Preload

预加载 (opens new window)

使用 Preload 方法, 在查询 User 时先去获取 CreditCard 的记录。

package main
import (
	"encoding/json"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

/*
constraint:OnUpdate:CASCADE 【当User表更新,也会同步给CreditCards】
OnDelete:SET NULL 【当User中数据被删除时,CreditCard关联设置为 NULL,不删除记录】
*/

type User struct {
	gorm.Model
	Username   string    `json:"username" gorm:"column:username"`
	CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

type CreditCard struct {
	gorm.Model
	Number string
	UserID uint
}

func main() {
	// 0、连接数据库
	dsn := "root:1@tcp(127.0.0.1:3306)/test_db?
	charset=utf8mb4&parseTime=True&loc=Local"
	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	// 1、预加载: 查找 user 时预加载相关 CreditCards
	//users := User{Username: "zhangsan"} // 只查找张三用户的信用卡信息
	users := []User{}
	db.Preload("CreditCards").Find(&users)
	strUser, _ := json.Marshal(&users)
	fmt.Println(string(strUser))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
上次更新: 2022/07/11, 00:25:56
GORM入门
import 本地 module

← GORM入门 import 本地 module→

最近更新
01
ctr和crictl显示镜像不一致
03-13
02
alpine镜像集成常用数据库客户端
03-13
03
create-cluster
02-26
更多文章>
Theme by Vdoing | Copyright © 2015-2024 op81.com
苏ICP备18041258号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式