Häufig gestellte Fragen zu Beziehungen
Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →
Wie erstelle ich eine selbstreferenzierende Beziehung?
Selbstreferenzierende Beziehungen sind Beziehungen, die auf sich selbst verweisen. Dies ist nützlich, wenn Sie Entitäten in baumartigen Strukturen speichern. Auch das "Adjazenzlisten"-Muster wird mit selbstreferenzierenden Beziehungen implementiert. Beispielsweise möchten Sie in Ihrer Anwendung eine Kategorie-Hierarchie erstellen. Kategorien können Unterkategorien enthalten, diese können weitere Unterkategorien enthalten usw. Hier sind selbstreferenzierende Beziehungen praktisch. Im Grunde sind selbstreferenzierende Beziehungen normale Beziehungen, die auf die Entität selbst verweisen. Beispiel:
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
OneToMany,
} from "typeorm"
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
text: string
@ManyToOne((type) => Category, (category) => category.childCategories)
parentCategory: Category
@OneToMany((type) => Category, (category) => category.parentCategory)
childCategories: Category[]
}
Wie verwende ich eine Beziehungs-ID ohne die Beziehung zu laden?
Manchmal möchten Sie in Ihrem Objekt die ID des verknüpften Objekts haben, ohne es zu laden. Beispiel:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number
@Column()
gender: string
@Column()
photo: string
}
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm"
import { Profile } from "./Profile"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@OneToOne((type) => Profile)
@JoinColumn()
profile: Profile
}
Wenn Sie einen Benutzer ohne verknüpftes profile laden, haben Sie keine Profilinformationen im Benutzerobjekt,
nicht einmal die Profil-ID:
User {
id: 1,
name: "Umed"
}
Aber manchmal möchten Sie die "Profil-ID" dieses Benutzers kennen, ohne das gesamte Profil zu laden.
Fügen Sie dazu einfach eine weitere Eigenschaft mit @Column in Ihrer Entität hinzu,
die genau wie die von Ihrer Beziehung erstellte Spalte benannt ist. Beispiel:
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm"
import { Profile } from "./Profile"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@Column({ nullable: true })
profileId: number
@OneToOne((type) => Profile)
@JoinColumn()
profile: Profile
}
Das war's. Beim nächsten Laden eines Benutzerobjekts enthält es eine Profil-ID:
User {
id: 1,
name: "Umed",
profileId: 1
}
Wie lade ich Beziehungen in Entitäten?
Der einfachste Weg, Ihre Entitätsbeziehungen zu laden, ist die relations-Option in FindOptions:
const users = await dataSource.getRepository(User).find({
relations: {
profile: true,
photos: true,
videos: true,
},
})
Ein alternativer und flexiblerer Ansatz ist die Verwendung von QueryBuilder:
const user = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.profile", "profile")
.leftJoinAndSelect("user.photos", "photo")
.leftJoinAndSelect("user.videos", "video")
.getMany()
Mit QueryBuilder können Sie innerJoinAndSelect statt leftJoinAndSelect verwenden
(den Unterschied zwischen LEFT JOIN und INNER JOIN entnehmen Sie Ihrer SQL-Dokumentation),
Beziehungsdaten nach Bedingungen verknüpfen, Sortierungen vornehmen usw.
Mehr über QueryBuilder.
Vermeiden Sie Initialisierer für Beziehungseigenschaften
Manchmal ist es praktisch, Ihre Beziehungseigenschaften zu initialisieren, z. B.:
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: Category[] = [] // see = [] initialization here
}
Bei TypeORM-Entitäten kann dies jedoch Probleme verursachen. Um das Problem zu verstehen, laden wir zunächst eine Question-Entität OHNE Initialisierer. Das geladene Objekt sieht so aus:
Question {
id: 1,
title: "Question about ..."
}
Beim Speichern wird die categories-Eigenschaft nicht verändert – da sie nicht gesetzt ist.
Mit Initialisierer sieht das geladene Objekt jedoch so aus:
Question {
id: 1,
title: "Question about ...",
categories: []
}
Beim Speichern prüft TypeORM, ob Kategorien in der Datenbank mit der Frage verknüpft sind –
und hebt alle Verknüpfungen auf. Warum? Weil eine Beziehung mit [] oder Inhalten so interpretiert wird,
als ob Elemente entfernt wurden. Es gibt keine andere Möglichkeit festzustellen, ob Objekte entfernt wurden.
Daher verursacht das Speichern eines solchen Objekts Probleme: Alle vorhandenen Kategorien werden entfernt.
Vermeiden Sie dieses Verhalten, indem Sie Arrays in Entitäten nicht initialisieren. Dieselbe Regel gilt für Konstruktoren – initialisieren Sie sie dort ebenfalls nicht.
Vermeiden Sie Fremdschlüssel-Constraints
Aus Performance-Gründen möchten Sie manchmal Beziehungen ohne Fremdschlüssel-Constraints.
Steuern Sie dies mit der Option createForeignKeyConstraints (Standard: true).
import { Entity, PrimaryColumn, Column, ManyToOne } from "typeorm"
import { Person } from "./Person"
@Entity()
export class ActionLog {
@PrimaryColumn()
id: number
@Column()
date: Date
@Column()
action: string
@ManyToOne((type) => Person, {
createForeignKeyConstraints: false,
})
person: Person
}
Vermeiden Sie zirkuläre Importfehler
Hier ein Beispiel, wie Sie Entitäten definieren können, ohne in bestimmten Umgebungen Fehler zu verursachen. Dabei importieren sich Action.ts und Person.ts gegenseitig für eine viele-zu-viele-Beziehung. Wir verwenden import type, um Typinformationen ohne JavaScript-Codegenerierung zu nutzen.
import { Entity, PrimaryColumn, Column, ManytoMany } from "typeorm"
import type { Person } from "./Person"
@Entity()
export class ActionLog {
@PrimaryColumn()
id: number
@Column()
date: Date
@Column()
action: string
@ManyToMany("Person", (person: Person) => person.id)
person: Person
}
import { Entity, PrimaryColumn, ManytoMany } from "typeorm"
import type { ActionLog } from "./Action"
@Entity()
export class Person {
@PrimaryColumn()
id: number
@ManyToMany("ActionLog", (actionLog: ActionLog) => actionLog.id)
log: ActionLog
}