Relaciones uno a uno
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Una relación uno a uno es aquella donde A contiene solo una instancia de B, y B contiene solo una instancia de A.
Tomemos como ejemplo las entidades User y Profile.
Un usuario puede tener solo un perfil, y un perfil solo puede pertenecer a un usuario.
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
}
Aquí añadimos @OneToOne al user y especificamos que el tipo de relación objetivo es Profile.
También añadimos @JoinColumn, que es obligatorio y debe establecerse solo en un lado de la relación.
El lado donde establezcas @JoinColumn contendrá en su tabla un "relation id" y claves foráneas hacia la tabla de la entidad objetivo.
Este ejemplo producirá las siguientes tablas:
+-------------+--------------+----------------------------+
| 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 |
+-------------+--------------+----------------------------+
Nuevamente, @JoinColumn debe establecerse solo en un lado de la relación, el que debe tener la clave foránea en la tabla de la base de datos.
Ejemplo de cómo guardar dicha relación:
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 las cascadas habilitadas, puedes guardar esta relación con solo una llamada a save.
Para cargar un usuario con su perfil incluido, debes especificar la relación en FindOptions:
const users = await dataSource.getRepository(User).find({
relations: {
profile: true,
},
})
O usando QueryBuilder puedes unirlas:
const users = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.profile", "profile")
.getMany()
Con la carga ansiosa (eager loading) activada en una relación, no necesitas especificarla en el comando find porque SIEMPRE se cargará automáticamente. Si usas QueryBuilder, las relaciones eager están desactivadas y debes usar leftJoinAndSelect para cargarla.
Las relaciones pueden ser unidireccionales y bidireccionales. Unidireccionales son relaciones con un decorador de relación solo en un lado. Bidireccionales son relaciones con decoradores en ambos lados de la relación.
Acabamos de crear una relación unidireccional. Hagámosla bidireccional:
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
}
Hemos hecho nuestra relación bidireccional. Nota: la relación inversa no tiene @JoinColumn.
@JoinColumn debe estar solo en un lado de la relación, en la tabla que poseerá la clave foránea.
Las relaciones bidireccionales te permiten unir desde ambos lados usando QueryBuilder:
const profiles = await dataSource
.getRepository(Profile)
.createQueryBuilder("profile")
.leftJoinAndSelect("profile.user", "user")
.getMany()