Zum Hauptinhalt springen

Eins-zu-eins-Beziehungen

Inoffizielle Beta-Übersetzung

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

Eine Eins-zu-eins-Beziehung liegt vor, wenn A genau eine Instanz von B enthält und B genau eine Instanz von A. Nehmen wir beispielsweise die Entitäten User und Profile. Ein Benutzer kann nur ein einzelnes Profil haben, und ein Profil gehört immer genau einem Benutzer.

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(() => Profile)
@JoinColumn()
profile: Profile
}

Hier haben wir @OneToOne zum user hinzugefügt und den Zielbeziehungstyp als Profile festgelegt. Zusätzlich haben wir @JoinColumn hinzugefügt, das erforderlich ist und nur auf einer Seite der Beziehung gesetzt werden muss. Auf der Seite, wo @JoinColumn gesetzt ist, enthält die Tabelle eine "Relation ID" und Fremdschlüssel zur Zieltabelle.

Dieses Beispiel erzeugt folgende Tabellen:

+-------------+--------------+----------------------------+
| profile |
+-------------+--------------+----------------------------+
| id | int | PRIMARY KEY AUTO_INCREMENT |
| gender | varchar(255) | |
| photo | varchar(255) | |
+-------------+--------------+----------------------------+

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

Nochmals: @JoinColumn darf nur auf einer Seite der Beziehung stehen – jener, die den Fremdschlüssel in der Datenbanktabelle haben muss.

Beispiel zum Speichern einer solchen Beziehung:

const profile = new Profile()
profile.gender = "male"
profile.photo = "me.jpg"
await dataSource.manager.save(profile)

const user = new User()
user.name = "Joe Smith"
user.profile = profile
await dataSource.manager.save(user)

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

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

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

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

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

Wenn Eager Loading für eine Beziehung aktiviert ist, müssen Sie sie nicht in find-Befehlen angeben – sie wird IMMER automatisch geladen. Bei QueryBuilder ist Eager Loading deaktiviert; Sie müssen leftJoinAndSelect verwenden.

Beziehungen können unidirektional oder bidirektional sein. Unidirektional bedeutet: Relations-Decorator nur auf einer Seite. Bidirektional bedeutet: Decorators auf beiden Seiten der Beziehung.

Wir haben bisher eine unidirektionale Beziehung. Machen wir sie bidirektional:

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

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

@Column()
gender: string

@Column()
photo: string

@OneToOne(() => User, (user) => user.profile) // specify inverse side as a second parameter
user: User
}
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm"
import { Profile } from "./Profile"

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

@Column()
name: string

@OneToOne(() => Profile, (profile) => profile.user) // specify inverse side as a second parameter
@JoinColumn()
profile: Profile
}

Jetzt ist unsere Beziehung bidirektional. Beachten Sie: Die inverse Beziehung hat kein @JoinColumn. @JoinColumn darf nur auf einer Seite stehen – der Tabelle, die den Fremdschlüssel besitzt.

Bidirektionale Beziehungen ermöglichen das Verknüpfen von beiden Seiten mit QueryBuilder:

const profiles = await dataSource
.getRepository(Profile)
.createQueryBuilder("profile")
.leftJoinAndSelect("profile.user", "user")
.getMany()