[英]How can I use single transaction with multiple query in repository mode in nestjs-typeorm
我為我的 NestJS 應用程序設置了一個設置,我在其中使用帶有 PostgreSQL 數據庫的 typeorm。 在設置中,我使用存儲庫模式來查詢數據庫。 現在我想在我的查詢中使用數據庫事務,但我無法使用事務,因為我正在使用一個事務和來自不同存儲庫的多個查詢,並且一個事務使用實體管理器,它必須用於查詢數據庫為了訪問 scope 中所有查詢的同一事務。
實體一
@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 中做類似的事情,如果可能的話我該如何實現呢?
QueryRunner
創建並控制單數據庫連接state事務是使用DataSource
或EntityManager
創建的。 例子:
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
創建並控制單數據庫連接state QueryRunner
提供單一數據庫連接。 事務是使用查詢運行器組織的。 單個事務只能在單個查詢運行器上建立。 您可以手動創建查詢運行器實例並使用它來手動控制事務 state。示例:
// 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://stackoverflow.com/a/70140732我認為這是具有多個存儲庫的解決方案的示例。
我找到了一個解決方案,我可以像sequelize一樣使用存儲庫和事務,它使用我們啟動事務時提供的管理器,管理器中有一個方法withRepository
object,它可以用來使用特定的查詢存儲庫。 所以我所做的是創建一個 BaseService,每次我必須查詢數據庫時,我將 function 作為最后一個參數傳遞給管理器,這也是可選的。 我在那里使用經理並執行以下操作。
manager.withRepository(this.repository).<queryFunction>()
就是這樣,如果你想要一個例子讓我知道我會實現它並在 github 存儲庫中共享。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.