3.7 KiB
Eager and Lazy Relations
Eager relations
Eager relations are loaded automatically each time you load entities from the database. For example:
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany} from "typeorm";
import {Question} from "./Question";
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(type => Question, question => question.categories)
questions: Question[];
}
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable} from "typeorm";
import {Category} from "./Category";
@Entity()
export class Question {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
text: string;
@ManyToMany(type => Category, category => category.questions, {
eager: true
})
@JoinTable()
categories: Category[];
}
Now when you load questions you don't need to join or specify relations you want to load. They will be loaded automatically:
const questionRepository = connection.getRepository(Question);
// questions will be loaded with its categories
const questions = await questionRepository.find();
Eager relations are working only when you use find* methods.
If you use QueryBuilder eager relations are disabled and you control by yourself what you are going to load using leftJoinAndSelect methods.
Eager relations can be used only on one side of relationship,
using eager: true on both sides of relationship is disallowed.
Lazy relations
Entities in lazy relations are loaded once you access them.
Such relations must be Promise type - you store your value in a promise,
and when you load them promise is returned as well. Example:
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany} from "typeorm";
import {Question} from "./Question";
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(type => Question, question => question.categories)
questions: Promise<Question[]>;
}
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable} from "typeorm";
import {Category} from "./Category";
@Entity()
export class Question {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
text: string;
@ManyToMany(type => Category, category => category.questions)
@JoinTable()
categories: Promise<Category[]>;
}
categories is a Promise. It means it is lazy and it can store only a promise with a value inside.
Example how to save such relation:
const category1 = new Category();
category1.name = "animals";
await connection.manager.save(category1);
const category2 = new Category();
category2.name = "zoo";
await connection.manager.save(category2);
const question = new Question();
question.categories = Promise.resolve([category1, category2]);
await connection.manager.save(question);
Example how to load objects inside lazy relations:
const question = await connection.getRepository(Question).findOneById(1);
const answers = await question.answers;
// you'll have all question's answers inside "answers" variable now
Note: if you came from other languages (Java, PHP, etc.) and used to use lazy relations everywhere - be careful. Those languages aren't asynchronous and lazy loading is achieved different way, that's why you don't handle with promises there. In JavaScript and Node.JS you have to use promises if you want to have lazy-loaded relations. This is non-standard technique and considered experimental in TypeORM.