Vai al contenuto principale

Relazioni uno-a-uno

Traduzione Beta Non Ufficiale

Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →

Una relazione uno-a-uno è un'associazione in cui A contiene un'unica istanza di B, e B contiene un'unica istanza di A.
Prendiamo come esempio le entità User e Profile.
Un utente può avere un solo profilo, e un profilo appartiene a un solo utente.

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
}

Qui abbiamo aggiunto @OneToOne all'utente (user) e specificato che il tipo di relazione target è Profile.
Abbiamo anche aggiunto @JoinColumn, obbligatorio e da impostare solo su un lato della relazione.
La tabella sul lato dove si imposta @JoinColumn conterrà un "relation id" e chiavi esterne verso la tabella dell'entità target.

Questo esempio produrrà le seguenti tabelle:

+-------------+--------------+----------------------------+
| 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 |
+-------------+--------------+----------------------------+

Ribadiamo: @JoinColumn deve essere impostato solo su un lato della relazione – quello che deve contenere la chiave esterna nella tabella del database.

Esempio di come salvare questa relazione:

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)

Con le cascades abilitate puoi salvare questa relazione con una sola chiamata save.

Per caricare un utente con il profilo associato, devi specificare la relazione nelle FindOptions:

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

Oppure usando QueryBuilder puoi effettuare un join:

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

Con l'eager loading abilitato su una relazione, non devi specificare le relazioni nel comando find perché verranno SEMPRE caricate automaticamente. Se usi QueryBuilder, le relazioni eager sono disabilitate e devi usare leftJoinAndSelect per caricare la relazione.

Le relazioni possono essere unidirezionali o bidirezionali.
Le unidirezionali hanno un decoratore di relazione solo su un lato.
Le bidirezionali hanno decoratori su entrambi i lati della relazione.

Abbiamo appena creato una relazione unidirezionale. Rendiamola bidirezionale:

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
}

Ora la relazione è bidirezionale. Nota: la relazione inversa non ha @JoinColumn.
@JoinColumn deve essere presente solo su un lato della relazione – nella tabella che possiederà la chiave esterna.

Le relazioni bidirezionali ti permettono di unire le relazioni da entrambi i lati usando QueryBuilder:

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