使用TypeORM和PostgreSQL数据库在NestJS中完美地实现ManytoMany(M2M)关系
目录
推荐超级课程:
这个指南教你如何使用TypeORM和PostgreSQL数据库在NestJS中完美地实现ManytoMany(M2M)关系。你将使用TypeORM的@ManyToMany
装饰器和查询构建器来建模两个实体之间的多对多关系。
你将学会:
- 如何创建两个实体,并使用TypeORM查询构建器添加多对多关系。
- 使用TypeORM
@JoinTable()
装饰器创建联接表。 - 使用PostgreSQL或MySQL添加你的多对多实体关系。
- 更新和保存ManytoMany关系
- 如何创建一个单一的POST方法来加载和应用TypeORM的ManytoMany关系。
- 使用级联删除多对多关系。
仔细看一看TypeORM的ManyToMany关系
多对多表示两个或更多实体。每个实体包含另一个实体的一个元素。所提到的元素与另一个实体中的多个元素相关联,反之亦然,以创建多对多关系。然后,这些多个元素使用一个连接/联接表来表示。
连接表现在将包含两个实体的主键的外键引用,这两个实体参与你的ManyToMany关系。
以这个例子说明:学生和课程。在这里,你将有如下形式的学生和课程实体:
- 学生
id(主键)
学生姓名
+-------------+--------------+----------------------------+
| 学生 |
+-------------+--------------+----------------------------+
| id | int(11) | 主键 自动增量 |
| 学生姓名 | varchar(255) | |
+-------------+--------------+----------------------------+
- 课程
id(主键)
课程名
+-------------+--------------+----------------------------+
| 课程 |
+-------------+--------------+----------------------------+
| id | int(11) | 主键 自动增量 |
| 课程名 | varchar(255) | |
+-------------+--------------+----------------------------+
到目前为止,这两个表是独立的,没有关联。这就是你现在要创建一个联接表,将这两者用它们各自的主键作为外键引用连接起来的地方。
让我们将连接表命名为StudentCourses
,用它来创建ManyToMany关系,以便Student
可以有许多Courses
,而Course
可以属于许多Students
。
基于这种关系,连接表将被表示如下:
学生ID(引用学生的外键)
课程ID(引用课程的外键)
+-------------+--------------+----------------------------+
| StudentCourse |
+-------------+--------------+----------------------------+
| 学生ID | int(11) | 主键 外键 |
| 课程ID | int(11) | 主键 外键 |
+-------------+--------------+----------------------------+
你的多对多关系将如下所示:
现在让我们深入研究并展示这个设置,并使用TypeORM、NestJS和PostgreSQL创建一个ManytoMany关系。
使用TypeORM实体创建多对多关系
在继续之前,请确保使用以下命令准备好您的NestJS:
npm i -g @nestjs/cli
nest new typeorm-manytomany
进入新创建的typeorm-manytomany
目录并安装必要的依赖项:
cd typeorm-manytomany
npm install @nestjs/typeorm typeorm pg
因为我们使用了两个实体,我们将分别使用模块来表示每个实体:
- 学生
nest g module student
nest g service student --no-spec
nest g controller student --no-spec
- 课程
nest g module course
nest g service course --no-spec
nest g controller course --no-spec
使用TypeORM实体创建多对多关系
TypeORM使用实体来表示实际数据库,而不是SQL语法。让我们深入研究并表示两个实体(学生和课程)并在它们之间添加多对多关系。
前往src/student
目录并创建一个student.entity.ts
文件。这将表示数据库中的学生如下:
// student.entity.ts
import {
Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import {
Course } from '../course/course.entity';
@Entity()
export class Student {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
}
同样,前往src/course
目录,并创建一个course.entity.ts
文件。这将表示数据库中的课程如下:
// course.entity.ts
import {
Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import {
Student } from '../student/student.entity';
@Entity()
export class Course {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
}
请注意,TypeORM使用装饰器来表示你的实体和字段在数据库中应如何安排。现在将ManyToMany关系添加到这两个实体中。
我们将从学生实体开始,更新代码如下所示:
import {
Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import {
Course } from '../course/course.entity';
@Entity()
export class Student {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(() => Course, course => course.students)
@JoinTable()
courses: Course[];
}
在这里:
@ManyToMany
装饰器定义了学生和课程之间的多对多关系。@JoinTable()
创建一个连接表。TypeORM将自动创建你的连接表,并添加相关的外键关系,无需手动操作。
这种关系还不完整。学生必须与课程相关联,course => course.students
必须指向学生所关联的课程,如下所示:
import {
Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import {
Student } from '../student/student.entity';
@Entity()
export class Course {
@PrimaryGe