我正在使用NestJS和TypeORM。我有几个模块,每个模块都包含服务。有些模块导入其他模块并使用它们的服务。
在这个例子中:
1. 我希望
我想将这两个操作都包装在事务中。我已经阅读了NestJS文档和TypeOrm文档,但无法找到如何正确执行此操作的答案。
关键在于
1. 如何支持这样的“嵌套事务”? 2. QueryRunner是否替代了Repository模式? 3. 我的服务应该持有Repository和Connection实例吗?Repository用于非事务操作,连接用于获取QueryRunner?
// 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);
}
}
...
}
在这个例子中:
1. 我希望
usersService.deleteUsersByCompany
是原子操作
2. 我希望companyService.deleteCompany
是原子操作
3. usersService.deleteUsersByCompany
和companyService.deleteCompany
都可以由用户触发我想将这两个操作都包装在事务中。我已经阅读了NestJS文档和TypeOrm文档,但无法找到如何正确执行此操作的答案。
关键在于
usersService.deleteUsersByCompany
是由companyService.deleteCompany
调用的。1. 如何支持这样的“嵌套事务”? 2. QueryRunner是否替代了Repository模式? 3. 我的服务应该持有Repository和Connection实例吗?Repository用于非事务操作,连接用于获取QueryRunner?
entityManager
,你可以从你选择的事务方法中获取它(包括所有类型的 TypeORM API,包括装饰器)deleteUsersByCompany(companyId: string, entityManager: EntityManager = this.usersRepository.manager)
在方法内部:entityManager.getRepository(User).createQueryBuilder('user') ...
应该是这样的,我会考虑更漂亮的实现方式。 - noam steinertypeorm-transactional-cls-hooked
,听起来很有前途,但它并不好用(https://github.com/odavid/typeorm-transactional-cls-hooked/issues/95),而且会引起其他问题。我仍在寻找合适的解决方案。 - Naor