首页 > 其他分享 >golang中GORM使用 many2many 多对多关联查询-详细案例

golang中GORM使用 many2many 多对多关联查询-详细案例

时间:2024-04-02 13:55:22浏览次数:26  
标签:profile gorm GORM golang many2many json user key id

  1. 表结构和数据

user表

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL,
  `user_key` bigint(20) NOT NULL,
  `account` char(32) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

为了测试将user_key和id写入同样的值

数据:

+----+----------+---------+
| id | user_key | account |
+----+----------+---------+
|  1 |        1 | user-1  |
+----+----------+---------+

profile 表

CREATE TABLE `profile` (
  `id` bigint(20) NOT NULL,
  `profile_key` bigint(20) NOT NULL,
  `desc` char(32) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

为了测试将profile_key和id写入同样的值

数据:

+----+-------------+-----------+
| id | profile_key | desc      |
+----+-------------+-----------+
|  2 |           2 | profile-1 |
|  3 |           3 | profile-2 |
+----+-------------+-----------+

中间表user_profile用来记录多对多关系,一个user可以有多个profile,一个profile也可以被多个user关联。

CREATE TABLE `user_profile` (
  `id` bigint(20) NOT NULL,
  `profile_id` bigint(20) NOT NULL,
  `user_id` bigint(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

数据:

+----+------------+---------+
| id | profile_id | user_id |
+----+------------+---------+
|  4 |          2 |       1 |
|  5 |          3 |       1 |
+----+------------+---------+
  1. golang代码

    package test_service
    
    import (
    	"encoding/json"
    	"fmt"
    	"gorm.io/driver/mysql"
    	"gorm.io/gorm"
    	"gorm.io/gorm/logger"
    )
    
    type User struct {
    	Id      int    `json:"id" gorm:"id"`
    	UserKey int    `json:"user_key" gorm:"user_key"`
    	Account string `json:"account" gorm:"account"`
    	// 默认用user表的id,去关联中间表 user_profile 的user_id, 用profile表的id去关联中间表 user_profile 的 profile_id
    	Profiles []Profile `gorm:"many2many:user_profile;joinForeignKey:user_id;joinReferences:profile_id;" json:"profiles"`
    
    	// 有些时候我们关联并不是用自身的id字段去关关联,通过foreignKey 指定 user_key,那么将用user 表的 user_key字段对应,user_profile 表的user_id字段
    	// 通过指定 references:profile_key ,将用 profile 表的 profile_key 字段对应,user_profile 表的 profile_id 字段
    
    	// 关联的字段,直接指定字段名的方式是可以的
    	AllProfiles []Profile `gorm:"many2many:user_profile;foreignKey:user_key;joinForeignKey:user_id;references:profile_key;joinReferences:profile_id;" json:"all_profiles"`
    	// 关联的字段,指定结构体中的属性名也可以,many2many 需要指定的中间表名,指定结构体转成表名会默认加 s,如果实际表名没有s,会报错
    	//AllProfiles []Profile `gorm:"many2many:user_profile;foreignKey:UserKey;joinForeignKey:UserId;references:ProfileKey;joinReferences:ProfileId;" json:"all_profiles"`
    }
    
    func (*User) TableName() string {
    	return "user"
    }
    
    type Profile struct {
    	Id         int    `json:"id" gorm:"id"`
    	ProfileKey int    `json:"profile_key" gorm:"profile_key"`
    	Desc       string `json:"desc" gorm:"desc"`
    }
    
    func (*Profile) TableName() string {
    	return "profile"
    }
    
    type UserProfile struct {
    	Id        int `json:"id" gorm:"id"`
    	ProfileId int `json:"profile_id" gorm:"profile_id"`
    	UserId    int `json:"user_id" gorm:"user_id"`
    }
    
    func (*UserProfile) TableName() string {
    	return "user_profile"
    }
    
    var db *gorm.DB
    
    func init() {
    	addr := "127.0.0.1:3306"
    	user := "user"
    	pass := "pass"
    	name := "test_1"
    	dsn := "%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local"
    	dsn = fmt.Sprintf(dsn, user, pass, addr, name)
    	db, _ = gorm.Open(mysql.Open(dsn), &gorm.Config{
    		Logger: logger.Default.LogMode(logger.Info),
    	})
    }
    
    func ManyToMany() {
    	var users []User
    	db.Preload("Profiles").Preload("AllProfiles").Where("id", 1).Find(&users)
    	by, _ := json.Marshal(users)
    	fmt.Println(string(by))
    }
    
  2. 调用ManyToMany 方法打印的json

    [
        {
            "id": 1,
            "user_key": 1,
            "account": "user-1",
            "profiles": [
                {
                    "id": 2,
                    "profile_key": 2,
                    "desc": "profile-1"
                },
                {
                    "id": 3,
                    "profile_key": 3,
                    "desc": "profile-2"
                }
            ],
            "all_profiles": [
                {
                    "id": 2,
                    "profile_key": 2,
                    "desc": "profile-1"
                },
                {
                    "id": 3,
                    "profile_key": 3,
                    "desc": "profile-2"
                }
            ]
        }
    ]
    
  3. 实际执行的sql

# 根据id找到user
SELECT * FROM `user` WHERE `id` = 1;
# 根据关联关系找中间表
 SELECT * FROM `user_profile` WHERE `user_profile`.`user_id` = 1;
# 根据中间表记录找到具体的profile数据 
 SELECT * FROM `profile` WHERE `profile`.`id` IN (2,3);

标签:profile,gorm,GORM,golang,many2many,json,user,key,id
From: https://www.cnblogs.com/jing1024/p/18110423

相关文章

  • Golang | Leetcode Golang题解之第4题寻找两个正序数组的中位数
    题目:题解:funcfindMedianSortedArrays(nums1[]int,nums2[]int)float64{iflen(nums1)>len(nums2){returnfindMedianSortedArrays(nums2,nums1)}m,n:=len(nums1),len(nums2)left,right:=0,mmedian1,median2:=0,0......
  • golang语言系列:Scrum、Kanban等敏捷管理策略
    云原生学习路线导航页(持续更新中)本文是golang语言系列文章,主要对编程通用技能Scrum、Kanban等敏捷管理策略进行学习1.什么是敏捷开发敏捷是一个描述软件开发方法的术语,它强调增量交付、团队协作、持续规划和持续学习。2001年,敏捷宣言提出:个体和交互胜过流程和......
  • python golang 安装私有库的用法
    python安装在requirements.txt增加了github私有安装库的依赖git+https://${GITHUB_TOKEN}@github.com/YOLOTECHNOLOGY/bossjob-auth-lib.git@${GITHUB_LIB_BRANCH}当前该库无法通过pipenv直接安装,需要进入到虚拟环境,通过pipinstall进行安装安装前需要设置GITHUB_......
  • golang: 分析查看汇编代码
    golang:分析查看汇编代码查看可执行文件可视化注意:linux用户需要额外运行goinstall--tagsnowaylandloov.dev/lensm@main​下载lensm:goinstallloov.dev/lensm@main运行lensm​:lensm.\main.exe​效果:​​Gobuild​gobuild-gcflags-S.\main.go​......
  • golang学习路线
    golang学习路线学习Golang的路线可以分为以下几个阶段:基础语法:了解Golang的基本语法结构,包括变量声明、控制流、函数、指针等。数据类型:熟悉Golang的基本数据类型,如整型、浮点型、字符串、数组、切片、Map等。并发编程:学习Golang的并发编程特性,包括goroutines、channels和互斥......
  • golang 读取文件内容,清空文件内容,把读取的内容写入到文件里
    packagemainimport( "encoding/json" "fmt" "io" "log" "os")typePvRelationListstruct{ Item[]PvRelationInfo`json:"item"`}typePvRelationInfostruct{ PodNamestring`json:"p......
  • 标准库unsafe:带你突破golang中的类型限制
    本文分享自华为云社区《突破语言golang中的类型限制》,作者:码乐。1简介在使用c语言编程时,常常因为类型的问题大伤脑筋,而其他语言比如java,python默认类型又是难以改变的,golang提供了一些方式用于喜欢hack的用户。2标准库unsafe的简单介绍官方说明标准库unsafe包含绕过Go......
  • Golang操作kafka遇到网络问题重试的案例
    草稿0、实际中会遇到网络抖动会导致消费者有一小段时间与kafka连接遇到问题~0、如何模拟网络问题?本地跑多个kafka实例直接关掉其中一个kafka服务??怎么模拟断网??1、kafka-go与sarama都演示一下2、一个consumer消费一个topic的例子;模拟网络问题可以把kafka服务关了~观察一下再开启k......
  • golang调试利器 dlv 的使用
    安装Github地址: https://github.com/go-delve/delve/如果是在本地调试,直接通过goinstall命令将其安装到本地的$GOPATH/bin下即可goinstallgithub.com/go-delve/delve/cmd/dlv@latest容器环境下由于不一定支持go,需要先安装go语言环境,会比较麻烦,可以直接将本地下载好......
  • 推荐 10 个非常有用的 Golang Libraries
    推荐10个非常有用的GolangLibraries原创 GoOfficialBlog GoOfficialBlog 2024-03-2518:16 山东 听全文Go语言的标准库非常好用。通常情况下,你不需要任何额外的库来完成任务。但是在某些情况下,可能需要使用一些库。今天将与你分享日常工作中很有用的10个......