es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo hacer que la relación OneToOne sea opcional para múltiples clases heredadas?

Supongamos que tengo una clase Animal que es heredada por Dog y Cat.

export class Animal extends BaseEntity{
    @PrimaryGeneratedColumn()
    id:number;
}

@Entity()
export class Cat extends Animal{
   ...
}

@Entity()
export class Dog extends Animal{
   ...
}

<code>
Ahora, quiero mostrar una relación OneToOne con su propietario. 

```ts
@Entity
export class Owner extends BaseEntity{
   ....

@OneToOne()
   pet:???
}

Owner es una clase que tiene un atributo pet que puede ser un Cat o un Dog.
¿Cómo puedo lograr esto utilizando TypeORM?


¿O estoy haciendo algo mal?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para lograr una relación OneToOne entre Owner y ya sea un Cat o un Dog, un enfoque es utilizar el decorador @JoinColumn y especificar la columna de clave foránea.

    Primero, necesitas agregar una columna de clave foránea a la entidad Owner que haga referencia a la clave principal de ya sea Dog o Cat:

    @Entity()
    export class Owner extends BaseEntity{
       ....
    
       @OneToOne(type => Animal, { eager: true })
       @JoinColumn()
       pet: Animal;
    }
    

    Luego, puedes utilizar el decorador @OneToOne para definir la relación entre Owner y Animal, y especificar Animal como la entidad objetivo. También necesitas usar { eager: true } para asegurarte de que la instancia asociada de Animal siempre se cargue cuando se cargue una instancia de Owner.

    Finalmente, puedes utilizar el decorador @JoinColumn para especificar la columna de clave foránea que se debe utilizar para la relación. Por defecto, TypeORM utilizará el nombre de la entidad y agregará un sufijo de la forma ‘_id’ (en este caso, ‘animal_id’) como el nombre de la columna de clave foránea. Sin embargo, dado que Dog y Cat son clases abstractas, necesitas especificar explícitamente la columna de clave foránea:

    @Entity()
    export class Cat extends Animal{
       ...
    
       @OneToOne(type => Owner, owner => owner.pet)
       @JoinColumn({ name: "cat_id" })
       owner: Owner;
    }
    
    @Entity()
    export class Dog extends Animal{
       ...
    
       @OneToOne(type => Owner, owner => owner.pet)
       @JoinColumn({ name: "dog_id" })
       owner: Owner;
    }
    

    En las entidades Cat y Dog, puedes utilizar el decorador @JoinColumn para especificar la columna de clave foránea que se debe utilizar para la relación. En este caso, necesitas especificar dos columnas de clave foránea diferentes (cat_id para la entidad Cat y dog_id para la entidad Dog) y también especificar el lado poseído de la relación para cada entidad (owner => owner.pet).

    Con esta configuración, puedes crear una instancia de Owner y asignar ya sea un Cat o un Dog al atributo pet:

    // crear un nuevo owner
    const owner = new Owner();
    await owner.save();
    
    // crear un gato
    const cat = new Cat();
    await cat.save();
    
    // asociar el gato con el owner
    owner.pet = cat;
    await owner.save();
    
    // crear un perro
    const dog = new Dog();
    await dog.save();
    
    // asociar el perro con el owner
    owner.pet = dog;
    await owner.save();
    

    De esta manera, puedes utilizar la entidad Owner para representar la relación uno a uno entre una mascota (ya sea un Cat o un Dog) y su dueño.

    Con respecto a la pregunta de si lo estás haciendo mal, realmente depende de tu caso de uso y los requisitos específicos de tu aplicación. Sin embargo, la solución mencionada anteriormente debería permitirte lograr la relación uno a uno deseada utilizando TypeORM de manera segura en cuanto a tipos.

Comments are closed.