在nestjs typeorm中,如何在存储库模式下使用单个事务和多个查询



我有一个NestJS应用程序的设置,我在其中使用PostgreSQL数据库的typeorm。在设置中,我使用存储库模式来查询数据库。现在,我想在查询中使用数据库事务,但我无法使用事务,因为我使用一个事务处理来自不同存储库的多个查询,而一个事务使用实体管理器,必须使用它来查询数据库,才能访问范围中所有查询的同一事务。

实体一

@Injectable()
export class EntityOneService extends BaseService<EntityOne> {
repository: Repository<EntityOne>;
constructor(private connection: Connection) {
super();
this.repository = this.connection.getRepository(EntityOne);
}
}

实体二

import { Injectable } from '@nestjs/common';
import { Connection, Repository } from 'typeorm';
import { EntityTwo } from '../entities/lesson.entity';
import { BaseService } from './baseService/base-service.service';
@Injectable()
export class EntityTwoService extends BaseService<EntityTwo> {
repository: Repository<EntityTwo>;
constructor(private connection: Connection) {
super();
this.repository = this.connection.getRepository(EntityTwo);
}
}

这是如何从数据库表初始化存储库的。现在我想在存储库模式下使用事务查询数据库。

const entityOne = await this.entityOneService.find()
const entityTwo = await this.entityTwoService.find()

我想用相同的事务查询两者。我在typeorm之前有一个用户sequelize,在sequelize中有一个名为transaction的方法,可以如下使用。

this.sequelize.transaction(async transaction => {
const entityOne = await this.entityOneService.findAll({transaction})
const entityTwo = await this.entityTwoService.findAll({transaction})
})

我想在typeorm中做类似的事情,如果可能的话,我该如何实现它?

https://stackoverflow.com/a/70140732我认为这是一个具有多个存储库的解决方案的示例。

事务

  • 创建和使用事务
  • 使用QueryRunner创建和控制单个数据库连接的状态

创建和使用事务

使用DataSourceEntityManager创建事务。示例:

await myDataSource.transaction(async (transactionalEntityManager) => {
// execute queries using transactionalEntityManager
});

await myDataSource.manager.transaction(async (transactionalEntityManager) => {
// execute queries using transactionalEntityManager
});

您想在事务中运行的所有内容都必须在回调中执行:

await myDataSource.manager.transaction(async (transactionalEntityManager) => {
await transactionalEntityManager.save(users);
await transactionalEntityManager.save(photos);
// ...
});

使用QueryRunner创建和控制单个数据库连接的状态

QueryRunner提供单个数据库连接。事务是使用查询运行器组织的。单个事务只能在单个查询运行器上建立。您可以手动创建查询运行器实例,并使用它手动控制事务状态。示例:

// create a new query runner
const queryRunner = dataSource.createQueryRunner();
// establish real database connection using our new query runner
await queryRunner.connect();
// now we can execute any queries on a query runner, for example:
await queryRunner.query("SELECT * FROM users");
// we can also access entity manager that works with connection created by a query runner:
const users = await queryRunner.manager.find(User);
// lets now open a new transaction:
await queryRunner.startTransaction();
try {
// execute some operations on this transaction:
await queryRunner.manager.save(user1);
await queryRunner.manager.save(user2);
await queryRunner.manager.save(photos);
// commit transaction now:
await queryRunner.commitTransaction();
} catch (err) {
// since we have errors let's rollback changes we made
await queryRunner.rollbackTransaction();
} finally {
// you need to release query runner which is manually created:
await queryRunner.release();
}

QueryRunner中有3种控制事务的方法:

  • startTransaction-在查询运行器实例中启动一个新事务
  • commitTransaction-提交使用查询运行器实例所做的所有更改
  • rollbackTransaction-回滚使用查询运行器实例所做的所有更改

来源:https://typeorm.io/transactions

我找到了一个解决方案,我可以像sequelize一样使用存储库和事务,它使用我们启动事务时提供的管理器,在管理器对象中有一个方法withRepository,它可以用来使用特定的存储库进行查询。所以我所做的是创建一个BaseService,每次我必须查询数据库时,我都会将函数中的管理器作为最后一个参数传递给它,这也是可选的。在那里,我使用经理并执行以下操作。

manager.withRepository(this.repository).<queryFunction>()

就是这样,如果你想要一个例子,让我知道我会实现它并在github存储库中共享。

最新更新