Zum Hauptinhalt springen

Many-to-One- / One-to-Many-Beziehungen

Inoffizielle Beta-Übersetzung

Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →

Eine Many-to-One- / One-to-Many-Beziehung liegt vor, wenn A mehrere Instanzen von B enthält, B jedoch nur eine Instanz von A.
Nehmen wir beispielsweise die Entitäten User und Photo.
Ein Benutzer kann mehrere Fotos besitzen, aber jedes Foto gehört ausschließlich zu einem einzelnen Benutzer.

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm"
import { User } from "./User"

@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number

@Column()
url: string

@ManyToOne(() => User, (user) => user.photos)
user: User
}
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm"
import { Photo } from "./Photo"

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number

@Column()
name: string

@OneToMany(() => Photo, (photo) => photo.user)
photos: Photo[]
}

Hier haben wir @OneToMany zur photos-Eigenschaft hinzugefügt und den Ziel-Beziehungstyp als Photo festgelegt.
@JoinColumn kann in einer @ManyToOne-/@OneToMany-Beziehung weggelassen werden.
@OneToMany kann nicht ohne @ManyToOne existieren.
Wenn Sie @OneToMany verwenden möchten, ist @ManyToOne erforderlich. Die Umkehrung gilt jedoch nicht: Wenn Sie nur die @ManyToOne-Beziehung benötigen, können Sie diese definieren, ohne dass @OneToMany in der zugehörigen Entität vorhanden sein muss.
Dort, wo Sie @ManyToOne setzen, wird die zugehörige Entität eine "Relation ID" und einen Fremdschlüssel besitzen.

Dieses Beispiel erzeugt folgende Tabellen:

+-------------+--------------+----------------------------+
| photo |
+-------------+--------------+----------------------------+
| id | int | PRIMARY KEY AUTO_INCREMENT |
| url | varchar(255) | |
| userId | int | FOREIGN KEY |
+-------------+--------------+----------------------------+

+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
+-------------+--------------+----------------------------+

Beispiel zum Speichern solcher Beziehungen:

const photo1 = new Photo()
photo1.url = "me.jpg"
await dataSource.manager.save(photo1)

const photo2 = new Photo()
photo2.url = "me-and-bears.jpg"
await dataSource.manager.save(photo2)

const user = new User()
user.name = "John"
user.photos = [photo1, photo2]
await dataSource.manager.save(user)

Alternativ können Sie folgendermaßen vorgehen:

const user = new User()
user.name = "Leo"
await dataSource.manager.save(user)

const photo1 = new Photo()
photo1.url = "me.jpg"
photo1.user = user
await dataSource.manager.save(photo1)

const photo2 = new Photo()
photo2.url = "me-and-bears.jpg"
photo2.user = user
await dataSource.manager.save(photo2)

Mit aktivierten Cascades können Sie diese Beziehung mit nur einem save-Aufruf speichern.

Um einen Benutzer mit seinen Fotos zu laden, müssen Sie die Beziehung in FindOptions angeben:

const userRepository = dataSource.getRepository(User)
const users = await userRepository.find({
relations: {
photos: true,
},
})

// or from inverse side

const photoRepository = dataSource.getRepository(Photo)
const photos = await photoRepository.find({
relations: {
user: true,
},
})

Oder mit QueryBuilder können Sie sie verknüpfen:

const users = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.photos", "photo")
.getMany()

// or from inverse side

const photos = await dataSource
.getRepository(Photo)
.createQueryBuilder("photo")
.leftJoinAndSelect("photo.user", "user")
.getMany()

Bei aktiviertem Eager Loading für eine Beziehung müssen Sie diese nicht im Find-Befehl angeben – sie wird IMMER automatisch geladen.
Bei Verwendung von QueryBuilder ist Eager Loading deaktiviert; Sie müssen leftJoinAndSelect verwenden, um die Beziehung zu laden.