Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

287
Vistas
¿Cuál es la forma correcta de trabajar con transacciones con NestJs y TypeORM?

Estoy usando NestJS con TypeORM. Tengo varios módulos y cada módulo contiene servicio. Hay algunos módulos que importan otros módulos y utilizan sus servicios.

 // In Person Module @Injectable() class UserService { constructor( @InjectRepository(User) private usersRepository: Repository<User> ) {} public async deleteUsersByCompany(companyId: string) { const usersToDelete = await this.usersRepository .createQueryBuilder('user') .where('user.companyId = :companyId', { companyId }) .getMany(); if (usersToDelete.length > 0) { await this.usersRepository.delete( usersToDelete.map((user) => user.id), ); } } ... } // Company Module @Injectable() class CompanyService { constructor( @InjectRepository(Company) private companysRepository: Repository<Company>, private usersService: UserService ) {} public async deleteCompany(companyId: string) { const companyToDelete = await this.companysRepository.find(companyId); if (companyToDelete) { await usersService.deleteUsersByCompany(companyToDelete.id) await this.companysRepository.delete(companyToDelete); } } ... }

En este ejemplo:

  1. Quiero que usersService.deleteUsersByCompany sea una operación atómica
  2. Quiero que companyService.deleteCompany sea una operación atómica
  3. Tanto usersService.deleteUsersByCompany como companyService.deleteCompany pueden ser activados por el usuario

Quiero envolver ambas acciones en transacción. He leído la documentación de NestJS y la documentación de TypeOrm, pero no pude encontrar una respuesta sobre cómo hacerlo correctamente.
Lo principal aquí es que usersService.deleteUsersByCompany llama a companyService.deleteCompany .

  1. ¿Cómo puedo admitir tales "transacciones anidadas"?
  2. ¿QueryRunner reemplaza el patrón de Repositorio?
  3. ¿Mis servicios deben contener tanto instancias de Repositorio como de Conexión? ¿Repositorio para operaciones no transaccionales y conexión para obtener QueryRunner?
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

La forma más fácil de usar la transacción es usar la API de EntityManager, vea un ejemplo simple de un microservicio:

 import { WRITE_CONNECTION } from '@my-api/common'; import { Injectable, Logger } from '@nestjs/common'; import { RpcException } from '@nestjs/microservices'; import { InjectEntityManager } from '@nestjs/typeorm'; import { EntityManager } from 'typeorm'; @Injectable() export class MyService { private logger = new Logger(MyService.name); constructor( @InjectEntityManager(WRITE_CONNECTION) private entityManager: EntityManager, ) {} async saveSomething(data: string): Promise<void> { try { return await this.entityManager.transaction(async (entityManager) => { const firstRepository = entityManager.getCustomRepository(FirstRepository); const secondRepository = entityManager.getCustomRepository(SecondRepository); const firstRecord = firstRepository.create({ data }); await firstRepository.save(firstRecord); const secondRecord = secondRepository.create({ data }); await secondRepository.save(secondRecord); // Save entities directly await entityManager.save([...]); }); } catch (error) { this.logger.error(`Failed saving something, error ${error.message}`, error.stack); throw new RpcException(error.message); } } }

Como puede ver, usamos el EntityManager para operaciones de lectura y escritura en la misma transacción que puede ejecutar una reversión automáticamente si alguna de estas operaciones falla.

Para más detalles consulta el repositorio de TypeORM con ejemplos aquí .

Entonces, si desea envolver ambas acciones en la misma transacción, debe llamar a un método y pasar el repositorio como parámetro. p.ej:

 async findOneItem( itemId: number, myRepository: MyRepository = this.myRepository, // Optional parameter if needed ) { return await myRepository.findOne(itemId); }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda