当前位置:网站首页>GORM 预加载和自引用
GORM 预加载和自引用
2022-04-22 22:01:00 【Dawnlighttt】
GORM 预加载和自引用
文章目录
预加载
从传统的外键约束说起
在传统的数据库设计中,如果我们想创建一个主表和从表,得在创建从表语句的时候添加外键约束(一般在创建的时候添加)。
[CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
比如现在有一个部门表和一个员工表,他们之间是一对多关系,部门表是主表,员工表是从表。那么在创建员工表的时候,我们得为它添加上外键约束:
# 先建立主表:department表
create table department(
id int primary key auto_increment,
dep_name varchar(20),
dep_location varchar(20)
);
# 创建从表 employee 并添加外键约束 emp_depid_fk
create table employee(
id int primary key auto_increment,
name varchar(20),
age int,
dep_id int, -- 外键对应主表的主键
-- 创建外键约束
constraint emp_depid_fk foreign key (dep_id) references department(id)
);
但是这样做存在一些问题,因为数据表的设计一般是在项目开发的起始阶段,我们不太可能一开始就把数据表设计的很完美,后期可能会对数据表之间的关系做一些调整,而添加外键约束无疑是提前把数据表之间的关系给写死了(如果没有添加级联操作的话),耦合度比较低。
ORM数据库
ORM数据库就考虑到了这一点,我们以GORM框架举例。在创建数据表的时候,可以不用对数据表添加任何约束,而是把这项任务延后到了创建models的时候,降低了耦合度,后期可以直接修改代码而不用去修改数据库。
我们来举一个例子,假如现在要创建三张数据表,学生表与成绩表是多对一,成绩表与课程表之间是一对多:
USE test01;
CREATE TABLE student(
sno VARCHAR(20),
NAME VARCHAR(20),
age INT
);
CREATE TABLE grade (
sno VARCHAR(20),
grade INT,
cno VARCHAR(20)
);
CREATE TABLE course (
cno VARCHAR(20),
cname VARCHAR(20)
);
INSERT INTO student VALUES("01", "张三", 19);
INSERT INTO student VALUES("02", "李四", 20);
INSERT INTO student VALUES("02", "王五", 21);
INSERT INTO grade VALUES("01", 90, "0001");
INSERT INTO grade VALUES("01", 80, "0002");
INSERT INTO grade VALUES("01", 30, "0003");
INSERT INTO grade VALUES("02", 80, "0001");
INSERT INTO grade VALUES("02", 50, "0002");
INSERT INTO grade VALUES("02", 60, "0003");
INSERT INTO course VALUES("0001", "数学");
INSERT INTO course VALUES("0002", "语文");
INSERT INTO course VALUES("0003", "英语");

我们在创建数据表的时候没有指定任何约束,而是把这项工作延后到了创建models的时候:
type student struct {
Sno string `gorm:"primary_key"`
Name string
Age int
Grades []grade `gorm:"foreignKey:Sno;association_foreignkey:Sno"`
}
func (student) TableName() string {
return "student"
}
type grade struct {
Sno string
Grade int
Cno string
}
func (grade) TableName() string {
return "grade"
}
type course struct {
Cno string `gorm:"primary_key"`
Cname string
Grades []grade `gorm:"foreignKey:Cno;association_foreignkey:Cno"`
}
func (course) TableName() string {
return "course"
}
在主表中,我们创建了从表映射结构体的切片,然后使用结构体tag来指定外键约束的字段,使用这种方式来表达主表和从表之间的关系。
预加载
创建好models以后,我们试着使用查询语句来查询表中的信息,比如查询学生表中张三的信息:
var st student
db.Where("Name=?", "张三").Find(&st)
// {01 张三 19 []}
我们可以发现,虽然学号、姓名和年龄都被打印出来了,但是从表的信息却没有打印出来,虽然在一般情况下,从表的信息是不用打印出来的,但是我们在student结构体中声明了Grades字段,这个字段的值按道理是应该和其他字段一样被打印出来的。
这个时候就需要使用预加载了:
db.Preload("Grades").Where("Name=?", "张三").Find(&st)
// {01 张三 19 [{01 90 0001} {01 80 0002} {01 30 0003}]}
Preload中指定的是映射结构体中的切片字段名。
自定义预加载
我们还可以自定义预加载,比如我们只想显示张三的数学成绩:
db.Preload("Grades", func(db *gorm.DB) *gorm.DB {
// 原生的sql语句, 这里的sno和cno是数据库中的字段,不是结构体中的字段
return db.Where("sno=? and cno=?", "01", "0001")
}).Where("Name=?", "张三").Find(&st)
// {01 张三 19 [{01 90 0001}]}
自引用
假如现在有一张员工表:

CREATE TABLE employee (
id INT,
lid INT,
NAME VARCHAR(20)
);
INSERT INTO employee VALUES(1, 0, "领导");
INSERT INTO employee VALUES(2, 1, "员工1");
INSERT INTO employee VALUES(3, 1, "员工2");
三个字段分别是员工编号、领导编号和员工姓名,某条数据的lid可能是另一条数据的id,即一个员工可能是另一个员工的领导,一张表中的数据构成了一对多关系,这就是自引用。
在models中可以这样来写tag:
type employee struct {
Id int
Lid int
Name string
Employees []employee `gorm:"foreignkey:Lid;association_foreignkey:Id"`
}
func (employee) TableName() string {
return "employee"
}
然后我们可以使用预加载来打印领导的信息:
var emp employee
db.Preload("Employees").Where("Name=?", "领导").Find(&emp)
fmt.Println(emp)
// {1 0 领导 [{2 1 员工1 []} {3 1 员工2 []}]}
参考资料:
版权声明
本文为[Dawnlighttt]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_49723651/article/details/124310253
边栏推荐
- Listing on the Shanghai Stock Exchange of CNOOC: market value of 6.515 billion and annual profit of 70.3 billion
- Basic practice of C language (001-1)
- Characteristics of Vickers Vickers proportional valve
- 怎么判断企业该做几级等保呢?做等保的意义又有哪些?
- Explain business agility in cloud computing in detail
- 100 billion level im independent development guide! Global instant messaging full set of codes 4 hours quick (II)
- Secyun assisted the "SaaS cloud management platform solution based on pseudo application integration framework" released by CETC 32
- Referrer Policy示例讲解
- 意大利阿托斯电磁阀的工作性质是什么?
- Common commands of Linux
猜你喜欢

企业应如何制定云计算使用中的灾难恢复计划?

强化学习(实践):REINFORCE,AC

2021下半年软件设计师上午真题及答案解析

Centos7安装mysql

ATOS阿托斯比例阀的工作原理及主要特性概述

Reinforcement learning (practice): dqn, double dqn, dueling dqn

想天浏览器:推荐几款好用的桌面浏览器

MySql--库的操作

pcba/ IPQ6010 802.11ax 2x2 2.4G&5G /2.5Gbps Ethernet Port

Crashsight general function & feature function introduction
随机推荐
Secyun assisted the "SaaS cloud management platform solution based on pseudo application integration framework" released by CETC 32
IPO of China first science and Technology Shenzhen Stock Exchange: another listed enterprise was born in Hubei with a market value of 8.3 billion
There's no need for real people to show their faces and shoot videos. Here's the method. Do we media for 20 days 4561
Listing on the Shanghai Stock Exchange of CNOOC: market value of 6.515 billion and annual profit of 70.3 billion
Transport layer - connectionless transport: UDP (2)
Crashsight general function & feature function introduction
Database resource load management (Part 2)
Sign up to open QKE container engine hosting version and container ecological Conference!
Characteristics of Vickers Vickers proportional valve
百思买Best Buy 网站EDI 测试流程
优化点
赛微微电上市首日破发:市值蒸发超15亿元,经营规模略输一筹
kubeflow创建新用户用户密码
How to use lightly to teach programming classes gracefully?
Pushing hand of industrial Internet innovation iteration
对象大小与指针压缩--JVM
A simple and easy-to-use file upload scheme
2.57-编写程序show_short, show_long和show_double,它们分别打印类型为short, long和double的C语言对象的字节表示。请试着在几种机器上运行。
删除 vector 内所有指定的元素
io_uring技术在分布式云原生数据库中的应用