• 多对多的关系

    多对多的关系

    多对多是一种 A 包含多个 B 实例,而 B 包含多个 A 实例的关系。我们以QuestionCategory 实体为例。Question 可以有多个 categories, 每个 category 可以有多个 questions。

    1. import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
    2. @Entity()
    3. export class Category {
    4. @PrimaryGeneratedColumn()
    5. id: number;
    6. @Column()
    7. name: string;
    8. }
    1. import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from "typeorm";
    2. import { Category } from "./Category";
    3. @Entity()
    4. export class Question {
    5. @PrimaryGeneratedColumn()
    6. id: number;
    7. @Column()
    8. title: string;
    9. @Column()
    10. text: string;
    11. @ManyToMany(type => Category)
    12. @JoinTable()
    13. categories: Category[];
    14. }

    @JoinTable()@ManyToMany关系所必需的。你必须把@JoinTable放在关系的一个(拥有)方面。

    此示例将生成以下表:

    1. +-------------+--------------+----------------------------+
    2. | category |
    3. +-------------+--------------+----------------------------+
    4. | id | int(11) | PRIMARY KEY AUTO_INCREMENT |
    5. | name | varchar(255) | |
    6. +-------------+--------------+----------------------------+
    7. +-------------+--------------+----------------------------+
    8. | question |
    9. +-------------+--------------+----------------------------+
    10. | id | int(11) | PRIMARY KEY AUTO_INCREMENT |
    11. | title | varchar(255) | |
    12. +-------------+--------------+----------------------------+
    13. +-------------+--------------+----------------------------+
    14. | question_categories_category |
    15. +-------------+--------------+----------------------------+
    16. | questionId | int(11) | PRIMARY KEY FOREIGN KEY |
    17. | categoryId | int(11) | PRIMARY KEY FOREIGN KEY |
    18. +-------------+--------------+----------------------------+

    如何保存这种关系:

    1. const category1 = new Category();
    2. category1.name = "animals";
    3. await connection.manager.save(category1);
    4. const category2 = new Category();
    5. category2.name = "zoo";
    6. await connection.manager.save(category2);
    7. const question = new Question();
    8. question.categories = [category1, category2];
    9. await connection.manager.save(question);

    启用级联后,只需一次save调用即可保存此关系。

    要在 categories 里面加载 question,你必须在FindOptions中指定关系:

    1. const questionRepository = connection.getRepository(Question);
    2. const questions = await questionRepository.find({ relations: ["categories"] });

    或者使用QueryBuilder

    1. const questions = await connection
    2. .getRepository(Question)
    3. .createQueryBuilder("question")
    4. .leftJoinAndSelect("question.categories", "category")
    5. .getMany();

    通过在关系上启用预先加载,你不必指定关系或手动加入,它将始终自动加载。

    关系可以是单向的和双向的。单向是仅在一侧与关系装饰器的关系。双向是与关系两侧的装饰者的关系。

    我们刚刚创建了一个单向关系。 让我们改为双向:

    1. import { Entity, PrimaryGeneratedColumn, Column, ManyToMany } from "typeorm";
    2. import { Question } from "./Question";
    3. @Entity()
    4. export class Category {
    5. @PrimaryGeneratedColumn()
    6. id: number;
    7. @Column()
    8. name: string;
    9. @ManyToMany(type => Question, question => question.categories)
    10. questions: Question[];
    11. }
    1. import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from "typeorm";
    2. import { Category } from "./Category";
    3. @Entity()
    4. export class Question {
    5. @PrimaryGeneratedColumn()
    6. id: number;
    7. @Column()
    8. title: string;
    9. @Column()
    10. text: string;
    11. @ManyToMany(type => Category, category => category.questions)
    12. @JoinTable()
    13. categories: Category[];
    14. }

    我们只是创建了双向关系。 注意,反向关系没有@JoinTable@JoinTable必须只在关系的一边。

    双向关系允许您使用QueryBuilder从双方加入关系:

    1. const categoriesWithQuestions = await connection
    2. .getRepository(Category)
    3. .createQueryBuilder("category")
    4. .leftJoinAndSelect("category.questions", "question")
    5. .getMany();