如何在NestJs Repositories中使用事务并完成开启与提交?
实现方案(基于 NestJS + TypeORM 0.3.x 版本)
要实现跨多个 Repository 的事务管控,核心是所有数据库操作必须使用同一个绑定了事务的 EntityManager 执行,不能直接使用构造函数注入的全局 Repository 实例。
首先修改 Service 依赖注入,引入 TypeORM 的 DataSource 实例:
import { Injectable } from '@nestjs/common'; import { InjectRepository, DataSource } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { A } from './entities/a.entity'; import { B } from './entities/b.entity'; @Injectable() export class MyService { constructor( @InjectRepository(A) private aRepository: Repository<A>, @InjectRepository(B) private bRepository: Repository<B>, // 注入数据源实例 private dataSource: DataSource, ) {} async doSomething() { // 启动事务,transaction 方法会自动处理开启、提交、回滚逻辑 await this.dataSource.transaction(async (entityManager) => { // 从事务管理器中获取对应实体的 Repository,所有操作都走当前事务 const aTxRepository = entityManager.getRepository(A); const bTxRepository = entityManager.getRepository(B); // 依次执行保存操作,注意必须加 await await aTxRepository.save(/* 你的保存参数 */); await bTxRepository.save(/* 你的保存参数 */); }) } }
关键说明
- 不需要手动写
begin/commit/rollback逻辑:transaction方法会在回调执行前自动开启事务,回调执行无报错自动提交,任意位置抛出错误自动回滚 - 禁止直接使用注入的
aRepository/bRepository执行事务内操作:注入的 Repository 默认绑定全局非事务管理器,操作不会被纳入当前事务管控 - 事务内所有异步数据库操作都必须加
await,否则事务会提前提交导致执行失败
手动管控事务的可选写法
如果需要更灵活的事务控制(比如自定义回滚时机),可以使用 QueryRunner 实现:
async doSomething() { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const aTxRepository = queryRunner.manager.getRepository(A); const bTxRepository = queryRunner.manager.getRepository(B); await aTxRepository.save(/* 参数 */); await bTxRepository.save(/* 参数 */); // 手动提交 await queryRunner.commitTransaction(); } catch (err) { // 出错手动回滚 await queryRunner.rollbackTransaction(); throw err; } finally { // 释放连接 await queryRunner.release(); } }
内容的提问来源于stack exchange,提问作者kalamar
相关产品推荐
相关产品推荐

