Ответ
Relations (отношения) в TypeORM — это декларативный способ определения связей между сущностями (таблицами) в базе данных. Они позволяют легко работать со связанными данными, как с обычными свойствами объектов в Node.js.
Основные типы отношений:
-
@OneToOne()— связь «один к одному». Часто используется для профилей или расширенных данных.@Entity() export class Profile { @PrimaryGeneratedColumn() id: number; @OneToOne(() => User, user => user.profile) // Указываем обратную связь @JoinColumn() // Столбец с внешним ключом будет в таблице `profile` user: User; } -
@OneToMany()и@ManyToOne()— связь «один ко многим». Самая распространенная.@Entity() export class User { @PrimaryGeneratedColumn() id: number; // У одного User много Photo @OneToMany(() => Photo, photo => photo.user) photos: Photo[]; } @Entity() export class Photo { @PrimaryGeneratedColumn() id: number; // Много Photo принадлежат одному User @ManyToOne(() => User, user => user.photos) @JoinColumn({ name: 'user_id' }) user: User; } -
@ManyToMany()— связь «многие ко многим». Создает промежуточную таблицу автоматически.@Entity() export class Question { @PrimaryGeneratedColumn() id: number; @ManyToMany(() => Category, category => category.questions) @JoinTable() // Эта аннотация ставится только на одной из сторон categories: Category[]; }
Стратегии загрузки (Loading Strategies):
- Eager: Данные загружаются автоматически вместе с основной сущностью. Может привести к N+1 проблеме, если неаккуратно использовать.
@ManyToOne(() => User, { eager: true }) // User будет подгружен всегда user: User; - Lazy: Данные загружаются только при явном обращении (возвращается Promise).
@ManyToOne(() => User, user => user.photos, { lazy: true }) user: Promise<User>; // Тип - Promise // Использование: const user = await photo.user;
Каскадные операции (cascade): Позволяют автоматически сохранять/удалять связанные сущности.
@OneToMany(() => Photo, photo => photo.user, { cascade: true })
photos: Photo[];
// При сохранении userRepository.save(user) сохранятся и все его photos
Практический пример с запросом:
// Найти пользователя со всеми его фотографиями
const userWithPhotos = await userRepository.findOne({
where: { id: 1 },
relations: ['photos'] // Жадная загрузка для этого запроса
});
// Или с помощью QueryBuilder для большей гибкости
const user = await userRepository
.createQueryBuilder('user')
.leftJoinAndSelect('user.photos', 'photo')
.where('user.id = :id', { id: 1 })
.getOne();