如何在nestjs中跨多个服务使用事务

问题描述 投票:0回答:1

如何在使用其他服务的服务函数中使用nestjs中的事务?

 async update(authContext: AuthContext, id: string, updatePortfolioDto: UpdatePortfolioDto, isSaved = false): Promise<Portfolio> {
   
    const queryRunner = this.dataSource.createQueryRunner();

  await queryRunner.connect();
  await queryRunner.startTransaction();
  try{
    await this.sleeveService.deleteForPortfolio(authContext, id);

    const updatedPortfolio = this.portfoliosRepository.update(id, portfolio);
    await queryRunner.commitTransaction();
    return updatedPortfolio

  }catch(err){
    await queryRunner.rollbackTransaction();
  }finally{
    await queryRunner.release();
  }
  }

更新是使用另一个服务sleeveService和portfolioRepository的服务方法

这是我当前的代码。但这不起作用,我该如何解决这个问题?

transactions nestjs typeorm
1个回答
0
投票

我有一个类似的问题,我解决了它(也许不是最好的方式)。但首先,有一个关于您的代码的重要说明。

根据 TypeOrm 文档

“请勿使用全局实体管理器。必须执行所有操作 使用提供的事务实体管理器。”

也就是说,您不应该在事务块内使用 portfoliosRepository 更新实体,而应使用 queryRunner.manager

现在,如果您想与此事务中与您的实体一起使用的其他服务进行交互,您的任务是传递一个 EntityManager 实例(queryRunner.manager)。您调用的其他服务方法必须采用 EntityManager 作为参数。还需要使用此管理器在此方法中保存/更新/删除实体。

我给你举个例子。我的交易如下所示:

        const queryRunner = this._dataSource.createQueryRunner()
        await queryRunner.connect()
        await queryRunner.startTransaction()
        try {
            this._logger.log(`Депозит баланса ${sum} на баланс задания ${task}`)

            const taskBalance: TaskBalanceEntity = await queryRunner.manager.findOne(TaskBalanceEntity, {
                where: {
                    taskId: task.id
                }
            })

            userBalance.value = userBalance.value - sum
            taskBalance.value = taskBalance.value + sum
            await queryRunner.manager.save(UserBalanceEntity, userBalance)
            await queryRunner.manager.save(TaskBalanceEntity, taskBalance)
            await this._taskBalanceDepositHistotyService.create(queryRunner.manager, taskBalance, sum)
            task.status = TaskStatus.ACTIVE
            await queryRunner.manager.save(TaskEntity, task)

            await queryRunner.commitTransaction()
            return
        } catch (error) {
            this._logger.error(error)
            await queryRunner.rollbackTransaction()
            throw new InternalServerErrorException("Ошибка при завершении транзакции")
        } finally {
            await queryRunner.release()
        }

在此示例中,您可以看到我正在调用另一个服务的方法this._taskBalanceDepositHistotyService.create(queryRunner.manager, taskBalance, sum),如下所示:

@Injectable()
export class TaskBalanceDepositHistoryService {
    constructor(
        @InjectRepository(TaskBalanceDepositHistoryEntity)
        private readonly taskBalanceDepositHistoryRepository: Repository<TaskBalanceDepositHistoryEntity>
    ) {}

    async create(entityManager: EntityManager, taskBalance: TaskBalanceEntity, value: number): Promise<void> {
        const taskBalanceDepositHistory = this.taskBalanceDepositHistoryRepository.create()
        taskBalanceDepositHistory.value = value
        taskBalanceDepositHistory.taskBalanceId = taskBalance.id
        await entityManager.save(TaskBalanceDepositHistoryEntity, taskBalanceDepositHistory)
    }
}

我知道这个解决方案不是最好的,我很乐意查看其他解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.