- TypeORM 教程
- TypeORM - 首页
- TypeORM - 简介
- TypeORM - 安装
- TypeORM - 创建一个简单的项目
- TypeORM - 连接 API
- TypeORM - 实体
- TypeORM - 关系
- TypeORM - 使用 Repository
- TypeORM - 使用 Entity Manager
- TypeORM - 查询构建器
- TypeORM - 查询操作
- TypeORM - 事务
- TypeORM - 索引
- TypeORM - 实体监听器和日志记录
- TypeORM 与 JavaScript
- TypeORM - 使用 MongoDB
- TypeORM 与 Express
- TypeORM - 迁移
- TypeORM - 使用 CLI
- TypeORM 有用资源
- TypeORM - 快速指南
- TypeORM - 有用资源
- TypeORM - 讨论
TypeORM - 关系
关系用于指数据库中表之间的关系。一般来说,当其中一个表具有引用另一个表主键的外键时,这两个表之间就存在关系。此功能使关系数据库更强大,并能有效地存储信息。
TypeORM 允许实体相互关联,进而关联数据库表。一般来说,关系可以分为四类,如下所示:
一对一 - 给定实体的一个对象只与目标实体的一个对象相关,反之亦然。例如,一个国家只有一个首都,同样一个城市也只有一个国家的首都。
多对一 - 给定实体的多个对象与目标实体的一个对象相关。例如,一个城市属于一个国家,但一个国家可以有多个城市。
一对多 - 与多对一相同,只是关系反过来了。
多对多 - 给定实体的多个对象与目标实体的多个对象相关。例如,一篇文章可以被标记在多个主题下,例如编程语言、金融等,同时一个特定的标签也可以有多篇文章。
TypeORM 还提供选项来增强实体的关系。它们如下所示:
- eager - 源实体对象也加载目标实体对象。
- cascade - 当源实体对象被插入或更新时,目标实体对象也会被插入或更新。
- onDelete - 当源实体对象被删除时,目标实体对象也会被删除。
- primary - 用于指定关系列是否为主键。
- nullable - 用于指定关系列是否可为空。
让我们详细了解不同类型的关系映射。
一对一
正如我们前面所了解的,它指的是一个表字段的实例包含另一个表字段的实例,反之亦然。让我们创建一个Details表:
Details.ts
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm"; @Entity() export class Details { @PrimaryGeneratedColumn() id: number; @Column() gender: string; @Column() country: string; }
让我们创建一个名为 Customer 的另一个实体:
Customer.ts
import {Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn} from "typeorm"; import {Details} from "./Details"; @Entity() export class Customer { @PrimaryGeneratedColumn() id: number; @Column() name: string; @OneToOne(type => Details) @JoinColumn() details: Details; }
这里:
我们已将OneToOne映射到Details表。@JoinColumn()包含一个“关系 ID”和指向Customer表的外键。我们可以如下在index.ts中保存关系:
const details = new Details(); details.gender = "female"; details.country = "india" await connection.manager.save(details); const customer = new Customer(); customer.name = 'customer1'; customer.details = Details; await connection.manager.save(Customer);
一对多和多对一
正如我们前面所了解的,它指的是第一个表字段的实例包含第二个表字段的多个实例,称为一对多映射;第一个表的多个实例只包含第二个表的一个实例,称为多对一映射。
考虑Student和project实体的例子,其中一名学生可以参与多个项目,但每个项目只由一名学生负责。
让我们创建一个Project实体:
Project
import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm"; import {Student} from "./Student"; @Entity() export class Project { @PrimaryGeneratedColumn() id: number; @Column() projects: string; @ManyToOne(type => Student, student => student.projects) student: Student; }
现在,我们创建Student实体如下:
import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm"; import {Project} from "./Project"; @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column() name: string; @OneToMany(type => Project, project => project.student) projects: Project[]; }
这里:
@OneToMany属性映射到Project,@ManyToOne属性映射到Student。但是,@OneToMany不能没有@ManyToOne,并且@ManyToOne属性包含“关系 ID”和外键。
我们可以在index.ts中保存连接:
const proj1 = new Project(); proj1.projects = "database management"; await connection.manager.save(proj1); const proj2 = new Project(); proj2.projects = "web application"; await connection.manager.save(proj2); const stud = new Student(); stud.name = "Student1"; stud.projects = [proj1, proj2]; await connection.manager.save(stud);
多对多
正如我们前面所了解的,它指的是一个表中的多条记录与另一个表中的多条记录相关。例如,大学学生可以同时选修多门课程,这意味着学生每学期可能会有四五门课程,一门课可以有多名学生。
我们可以简单地总结一下,一个学生可以选修多门课程,一门课程可以有多名学生。让我们创建一个Classes实体:
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm"; @Entity() export class Classes { @PrimaryGeneratedColumn() id: number; @Column() name: string; }
现在,我们创建Student实体如下:
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable} from "typeorm"; import {Classes} from "./Classes"; @Entity() export class Student { @PrimaryGeneratedColumn() id: number; @Column() name: string; @Column() subjects: string; @ManyToMany(type => Classes) @JoinTable() classes: Classes[]; }