gorm之项目实战-使用gen以及定义表间关系

news2025/1/16 5:08:10

gorm之项目实战

ER图

Image1

关系整理

  1. 一对一关系:

    • User 和 UserLog: 一个用户对应一个用户日志,通过 User 模型的主键与 UserLog 模型的外键建立一对一关系。
  2. 一对多关系:

    • User 和 Teacher: 一个用户可以对应多个老师,通过 Teacher 模型的外键(UserID)与 User 模型的主键建立一对多关系。
    • User 和 Student: 一个用户可以对应多个学生,通过 Student 模型的外键(UserID)与 User 模型的主键建立一对多关系。
    • Teacher 和 Class: 一个老师可以有多个班级,通过 Class 模型的外键(TeacherID)与 Teacher 模型的主键建立一对多关系。
    • Student 和 StudentClass: 一个学生可以有多个班级,通过 StudentClass 模型的外键(StudentID)与 Student 模型的主键建立一对多关系。
    • Student 和 Attendance: 一个学生可以有多条考勤记录,通过 Attendance 模型的外键(StudentID)与 Student 模型的主键建立一对多关系。
  3. 多对多关系:

    • Student 和 Class: 一个学生可以属于多个班级,一个班级可以有多个学生,通过 StudentClass 模型作为中间表,建立多对多关系。
    • Teacher 和 Class: 一个老师可以教授多个班级,一个班级可以有多个老师,通过 Class 模型的外键(TeacherID)与 Teacher 模型的主键,建立多对多关系。
  4. 一对多逆向关系:

    • Parent 和 Student: 一个家长可以有多个子女,通过 Student 模型的外键(StudentID)与 Parent 模型的主键建立一对多逆向关系。

使用gen自动化生成代码

首先使用gen工具生成代码

package main

// gorm gen configure

import (
    "fmt"

    "gorm.io/driver/mysql"
    "gorm.io/gorm"

    "gorm.io/gen"
)

const MySQLDSN = "root:root@tcp(127.0.0.1:3306)/school?charset=utf8mb4&parseTime=True"

func connectDB(dsn string) *gorm.DB {
    db, err := gorm.Open(mysql.Open(dsn))
    if err != nil {
        panic(fmt.Errorf("connect db fail: %w", err))
    }
    return db
}

func main() {
    // 指定生成代码的具体相对目录(相对当前文件),默认为:./query
    // 默认生成需要使用WithContext之后才可以查询的代码,但可以通过设置gen.WithoutContext禁用该模式
    g := gen.NewGenerator(gen.Config{
        // 默认会在 OutPath 目录生成CRUD代码,并且同目录下生成 model 包
        // 所以OutPath最终package不能设置为model,在有数据库表同步的情况下会产生冲突
        // 若一定要使用可以通过ModelPkgPath单独指定model package的名称
        OutPath: "dao/query",
        /* ModelPkgPath: "dal/model"*/

        // gen.WithoutContext:禁用WithContext模式
        // gen.WithDefaultQuery:生成一个全局Query对象Q
        // gen.WithQueryInterface:生成Query接口
        Mode: gen.WithDefaultQuery | gen.WithQueryInterface,
    })

    // 通常复用项目中已有的SQL连接配置db(*gorm.DB)
    // 非必需,但如果需要复用连接时的gorm.Config或需要连接数据库同步表信息则必须设置
    g.UseDB(connectDB(MySQLDSN))

    // 从连接的数据库为所有表生成Model结构体和CRUD代码
    // 也可以手动指定需要生成代码的数据表
    g.ApplyBasic(g.GenerateAllTable()...)

    // 执行并生成代码
    g.Execute()
}

在gen生成的model中定义外键联系

生成的model代码在dao/model

Image2

我们需要在这些Model中定义外键关系,先把User表and Teacher表与Student表关系定义

Image3

一对一关系

首先先确定主表和附表,主表

  • 主表:User,逐渐:UserID

  • 附表:Student,外键:UserID

  • 附表:Teacher,外键:UserID

  • 在model.User中添加两个

Image4

  • 把generate改下,我们要用改过的模型生成query

  •     g.ApplyBasic(
            model.Student{},
            model.Teacher{},
            model.User{},
            model.UserLog{},
            model.Class{},
            model.Course{},
            model.Attendance{},
            model.StudentClass{},
            model.Parent{},
        )
        // 执行并生成代码
        g.Execute()
    

增加用户业务逻辑

这边按UserType新建对应的学生和教师

func CreateUser(c *gin.Context) {
    var req request.CreateUserRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "error": "创建用户请求失败,无效的请求参数"})
        return
    }

    var user model.User

    switch req.UserType {
    case "Student":
        user = model.User{
            Username:  req.Username,
            Password:  req.Password,
            OpenID:    req.OpenID,
            Avatar:    req.Avatar,
            LastLogin: time.Now(),
            UserType:  req.UserType,
            IsValid:   req.IsValid,
            Student: model.Student{
                StudentName: req.Username,
            },
        }
    case "Teacher":
        user = model.User{
            Username:  req.Username,
            Password:  req.Password,
            OpenID:    req.OpenID,
            Avatar:    req.Avatar,
            LastLogin: time.Now(),
            UserType:  req.UserType,
            IsValid:   req.IsValid,
            Teacher: model.Teacher{
                TeacherName: req.Username,
            },
        }
    default:
        c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "error": "无效的用户类型"})
        return
    }

    err := query.User.WithContext(context.Background()).Create(&user)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"code": http.StatusInternalServerError, "error": fmt.Sprintf("创建用户请求失败,无法创建用户: %v", err)})
        return
    }

    c.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "message": "用户创建成功"})
}

Image5

删除用户业务逻辑

// DeleteUser 处理删除用户请求的函数
func DeleteUser(c *gin.Context) {
	userIDStr := c.Param("id") // Assuming the route has "id" parameter

	var User model.User
	userID, err := strconv.ParseInt(userIDStr, 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "error": "Failed to delete user, invalid user ID"})
		return
	}
	//var user model.User
	config.GVA_DB.Take(&User, userID)
	ret := config.GVA_DB.Select("Student").Delete(&User)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": http.StatusInternalServerError, "error": fmt.Sprintf("Failed to delete user, unable to delete user: %v", err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "message": fmt.Sprintf("User deleted successfully, RowsAffected: %v", ret.RowsAffected)})
}

Image6

更新

这里因为是主表,逻辑上之更新注表就好,后面改相应表的在编写逻辑

主要是改改头像什么的


查找

// GetUser 处理获取单个用户请求的函数
func GetUser(c *gin.Context) {
	userIDStr := c.Param("id") // Assuming the route has "id" parameter

	u := query.User
	userID, err := strconv.ParseInt(userIDStr, 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "error": "Failed to get user, invalid user ID"})
		return
	}

	user, err := query.User.WithContext(context.Background()).Where(query.User.UserID.Eq(int32(userID))).Preload(u.Student, u.Teacher).First()

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": http.StatusInternalServerError, "error": fmt.Sprintf("Failed to get user, unable to get user: %v", err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "user": user})
}

// GetAllUsers 处理获取所有用户请求的函数
func GetAllUsers(c *gin.Context) {
	u := query.User
	users, err := query.User.WithContext(context.Background()).Preload(u.Student, u.Teacher).Find()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"code": http.StatusInternalServerError, "error": fmt.Sprintf("Failed to get all users, unable to get user list: %v", err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "users": users})
}

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

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

相关文章

电路中模拟地和数字地的分割方法

电路中只要是地,最终都要接到一起,然后入大地。如果不接在一起就是“浮地”,存在压差,容易积累电荷,造成静电。 地是参考0电位,所有电压都是参考地得出的,地的标准一致,故各种地应短…

rasa train nlu详解:1.1-train_nlu()函数

本文使用《使用ResponseSelector实现校园招聘FAQ机器人》中的例子,主要详解介绍train_nlu()函数中变量的具体值。 一.rasa/model_training.py/train_nlu()函数   train_nlu()函数实现,如下所示: def train_nlu(config: Text,nlu_data: Op…

transformers安装避坑

1.4 下载rust编辑器 看到这里你肯定会疑惑了,我们不是要用python的吗? 这个我也不知道,你下了就对了,不然后面的transformers无法安装 因为是windows到官网选择推荐的下载方式https://www.rust-lang.org/tools/install。 执行文…

使用ResponseSelector实现校园招聘FAQ机器人

本文主要介绍使用ResponseSelector实现校园招聘FAQ机器人,回答面试流程和面试结果查询的FAQ问题。FAQ机器人功能分为业务无关的功能和业务相关的功能2类。 一.data/nlu.yml文件   与普通意图相比,ResponseSelector训练数据中的意图采用group/intent格…

【Armstrong公理】【求闭包和候选码】【判断范式】

1. Armstrong公理 2.求闭包和候选码 3.判断范式

WebSphere Liberty 8.5.5.9 (二)

WebSphere Liberty 8.5.5.9 (二) encode and decode Pre WebSphere Liberty 8.5.5.9 xor and AES 提取 D:\wlp-webProfile7-java8-8.5.5.9\wlp\lib 下必要加解密包 com.ibm.ws.crypto.certificateutil_1.0.12.jar com.ibm.ws.crypto.passwordutil_1…

2023 年合成数据的用例和应用

合成数据,也称为人工生成的数据,为数据科学应用中经常遇到的问题(例如数据隐私和小数据量)提供了解决方案。我们列出了不同行业和部门/业务单位中合成数据的功能和最常见的用例。 合成数据支持哪些与行业无关的用例/功能&#xf…

浅谈高并发以及三大利器:缓存、限流和降级

引言 高并发背景 互联网行业迅速发展,用户量剧增,系统面临巨大的并发请求压力。 软件系统有三个追求:高性能、高并发、高可用,俗称三高。三者既有区别也有联系,门门道道很多,全面讨论需要三天三夜&#…

Install Nginx in Linux

Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。 1.yum 安装 nginx [rootVM-8-7-centos nginx]# yum install -y nginx Loaded plugins: fastestmirror, lang…

移动端模型部署框架

移动端模型部署框架 1. MNN整体特点轻量性通用性高性能易用性架构设计主体工具致谢移动端模型部署框架 1. MNN https://www.yuque.com/mnn/cn/about MNN是全平台轻量级高性能深度学习引擎,广泛支持了阿里巴巴在计算机视觉、语音识别技术、自然语言处理等领域的70多个AI应用…

vue3 文字轮播打字机效果

实现效果 1.安装依赖 npm install duskmoon/vue3-typed-js 2.html <div class"title_left_1"><Typed :options"options" class"typedClass"><div class"typing"></div></Typed> </div> 3.ts…

基于单片机的空调智能控制器的设计

**单片机设计介绍&#xff0c;基于单片机的空调智能控制器的设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的空调智能控制器需要具备输入输出端口、定时器、计数器等模块&#xff0c;以便对空调进行精确控制。下…

单词规律问题

给定一种规律 pattern 和一个字符串 s &#xff0c;判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配&#xff0c;例如&#xff0c; pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 示例1: 输入: pattern “abba”, s “dog cat cat d…

Java学习 10.Java-数组习题

一、创建一个 int 类型的数组, 元素个数为 100, 并把每个元素依次设置为 1 - 100 代码实现 public static void main(String[] args) {int[] arrnew int[100];for (int i 0; i < arr.length; i) {arr[i]i1;}System.out.println(Arrays.toString(arr));} 运行结果 二、改变…

僵尸进程问题如何处理

现象&#xff1a; 工作中遇到docker内有很多的僵尸进程&#xff0c;导致CPU过高&#xff0c;直接卡死。 原因&#xff1a; 每个进程都有一个唯一的标识&#xff0c;称为 pid&#xff0c;pid 是一个非负的整数值&#xff0c;使用 ps 命令可以查看其中 PID 是表示进程号。系统中…

开发知识点-Ant-Design-Vue

Ant-Design-Vue a-input a-input Vue组件 a-spin 加载中的效果 data字段 mounted钩子函数 Ant Design Vue 组件库 list-type“picture-card” 上传的图片作为卡片展示 name show-upload-list action :beforeUpload“handleBeforeUpload” :headers“customHeaders” :disabl…

公开数据集:灵长类动物多通道感觉运动皮层电生理学的研究

Nonhuman Primate Reaching with Multichannel Sensorimotor Cortex Electrophysiology. 1 公开数据集网址&#xff1a;https://zenodo.org/records/3854034 目录 General DescriptionPossible usesVariable namesDecoder ResultsVideosSupplementsContact InformationCitation…

数据结构与算法【二分查找】Java实现

需求&#xff1a;在有序数组 A 内&#xff0c;查找值target 如果找到返回索引如果找不到返回 -1 前提 给定一个内含 n 个元素的有序数组 A&#xff0c;一个待查值 target 1 设置 i0&#xff0c;jn-1 2 如果 i \gt j&#xff0c;结束查找&#xff0c;没找到 3 设置 m (…

afsim 下载链接

afsim是一个通用的建模框架&#xff0c;能够构建典型的虚拟威胁环境和相关模型。能够以可视化形式分析软件仿真结果&#xff0c;显示平台、路由、传感器区域等内容&#xff0c;能够基于事件生成图表&#xff0c;进行结果统计&#xff0c;能够按类型进行统计分析。 苦于网上没有…

36 Gateway网关 快速入门

3.Gateway服务网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式…