Many-to-One- / One-to-Many-Beziehungen
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.