NestJS

Nest

Tutorial Nest: Creación de entidades y tablas

Nest entidades: definición y uso. Aprende a definir y usar entidades en Nest con ejemplos prácticos y detallados.

TypeORM y NestJS forman una sólida combinación para gestionar bases de datos relacionales.

TypeORM permite definir entidades, relaciones y realizar consultas, mientras que NestJS facilita la creación de repositorios y migraciones. Juntos, ofrecen una solución completa y eficiente para el manejo de datos en aplicaciones NestJS.

Antes de comenzar con la creación de entidades y tablas, es necesario configurar TypeORM en un proyecto NestJS.

Creación de entidades

Las entidades en TypeORM representan las tablas en la base de datos y se definen usando clases y decoradores.

Ejemplo

Crear una entidad "Usuario".

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity('usuarios')
export class Usuario {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  nombre: string;

  @Column()
  email: string;

  @Column({ default: true })
  isActive: boolean;
}
  • @Entity('usuarios'): Este decorador define la clase como una entidad y le da un nombre a la tabla.
  • @PrimaryGeneratedColumn(): Define una columna primaria que es auto-generada.
  • @Column(): Define una columna regular.

Uso de relaciones entre entidades

TypeORM soporta múltiples relaciones entre entidades:

  • Uno a Uno (OneToOne)
  • Uno a Muchos (OneToMany)
  • Muchos a Uno (ManyToOne)
  • Muchos a Muchos (ManyToMany)

Relación OneToOne

Una relación OneToOne significa que una entidad se relaciona con otra entidad y ambas solo pueden tener una relación entre sí.

Ejemplo:

Supongamos que se tienen dos entidades: Usuario y Perfil. Cada usuario tiene un perfil y cada perfil pertenece a un único usuario.

Código de la entidad Usuario:

@Entity()
export class Usuario {
  @PrimaryGeneratedColumn()
  id: number;

  @OneToOne(() => Perfil, perfil => perfil.usuario)
  @JoinColumn()
  perfil: Perfil;
}

Código de la entidad Perfil:

@Entity()
export class Perfil {
  @PrimaryGeneratedColumn()
  id: number;

  @OneToOne(() => Usuario, usuario => usuario.perfil)
  usuario: Usuario;
}

El decorador @JoinColumn indica que la entidad Usuario es la propietaria de la relación y que la tabla usuario contendrá la clave foránea de perfil.

Relación OneToMany y ManyToOne

OneToMany y ManyToOne se utilizan juntas.

Supongamos que un usuario puede tener múltiples tareas, pero cada tarea pertenece a un único usuario.

Código de la entidad Usuario:

@Entity()
export class Usuario {
  @PrimaryGeneratedColumn()
  id: number;

  @OneToMany(() => Tarea, tarea => tarea.usuario)
  tareas: Tarea[];
}

Código de la entidad Tarea:

@Entity()
export class Tarea {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(() => Usuario, usuario => usuario.tareas)
  usuario: Usuario;
}

Aquí, un usuario tiene múltiples tareas, pero cada tarea está asociada a un solo usuario.

La propiedad tareas en Usuario contiene un array de objetos Tarea.

Relación ManyToMany

Esta relación se utiliza cuando múltiples registros de una entidad pueden estar relacionados con múltiples registros de otra entidad.

Ejemplo:

Código de la entidad Estudiante:

@Entity()
export class Estudiante {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToMany(() => Curso, curso => curso.estudiantes)
  @JoinTable()
  cursos: Curso[];
}

Código de la entidad Curso:

@Entity()
export class Curso {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToMany(() => Estudiante, estudiante => estudiante.cursos)
  estudiantes: Estudiante[];
}

En este ejemplo, la entidad Estudiante tiene una relación many-to-many con la entidad Curso.

La propiedad cursos en Estudiante contiene un array de objetos Curso.

Por otro lado, la entidad Curso también tiene una relación many-to-many con la entidad Estudiante.

El decorador @JoinTable() indica que la entidad Estudiante es la propietaria de la relación y que se generará una tabla de unión (intermedia) para manejar la relación many-to-many.

Al utilizar estas relaciones en entidades y configurar TypeORM con synchronize: true, las tablas de la base de datos se generarán automáticamente a partir de las entidades y sus relaciones.

Nota: En un entorno de producción, es recomendable desactivar la sincronización automática y gestionar el esquema de la base de datos mediante migraciones.

Repositorios y manipulación de datos

Una vez que las entidades están definidas y las relaciones establecidas, NestJS y TypeORM ofrecen mecanismos para manipular y consultar la base de datos a través de repositorios.

Repositorios

Un repositorio es una clase que permite realizar operaciones CRUD (crear, leer, actualizar y eliminar) sobre una entidad.

Para cada entidad, TypeORM crea automáticamente un repositorio.

Ejemplo: Para acceder al repositorio de la entidad Usuario, se puede inyectar el repositorio en cualquier servicio:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Usuario } from './usuario.entity';

@Injectable()
export class UsuarioService {
  constructor(
    @InjectRepository(Usuario)
    private usuarioRepository: Repository<Usuario>,
  ) {}

  findAll(): Promise<Usuario[]> {
    return this.usuarioRepository.find();
  }

  findOne(id: number): Promise<Usuario> {
    return this.usuarioRepository.findOne(id);
  }

  async remove(id: number): Promise<void> {
    await this.usuarioRepository.delete(id);
  }
}

Consultas personalizadas

Los repositorios ofrecen métodos básicos para operaciones CRUD, pero en casos más complejos, se pueden construir consultas personalizadas.

Ejemplo: Buscar usuarios activos con un nombre específico.

async findActiveByName(nombre: string): Promise<Usuario[]> {
  return this.usuarioRepository.createQueryBuilder('usuario')
    .where('usuario.nombre = :nombre', { nombre })
    .andWhere('usuario.isActive = :isActive', { isActive: true })
    .getMany();
}

Migraciones

A medida que la aplicación crece, es posible que se necesite modificar la estructura de las entidades.

Las migraciones son una forma de gestionar y rastrear estos cambios en la estructura de la base de datos.

Para utilizar migraciones, primero, es necesario modificar la configuración de TypeORM:

TypeOrmModule.forRoot({
  // ... otras configuraciones ...
  migrations: [__dirname + '/migrations/*{.ts,.js}'],
  cli: {
    migrationsDir: 'src/migrations',
  },
  synchronize: false,
})

Luego, se pueden generar y ejecutar migraciones utilizando la CLI de TypeORM.

Conclusión

La integración de NestJS con TypeORM facilita la creación y manejo de entidades y tablas en la base de datos. Las entidades representan estructuras de datos, mientras que los decoradores permiten definir las características y relaciones entre estas estructuras.

Certifícate en Nest con CertiDevs PLUS

Ejercicios de esta lección Creación de entidades y tablas

Evalúa tus conocimientos de esta lección Creación de entidades y tablas con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de Nest

Accede a todas las lecciones de Nest y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Certificados de superación de Nest

Supera todos los ejercicios de programación del curso de Nest y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender el concepto de entidades y tablas en TypeORM.
  2. Aprender a crear entidades y tablas.
  3. Conocer cómo funcionan las relaciones entre entidades.
  4. Entender cómo se utilizan los repositorios para manipular datos.
  5. Conocer cómo funcionan las migraciones en TypeORM.