Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

917
Views
¿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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!