簡體   English   中英

如何在 nestjs-typeorm 中以存儲庫模式使用單個事務和多個查詢

[英]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

創建和使用事務

事務是使用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創建並控制單數據庫連接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://typeorm.io/transactions

https://stackoverflow.com/a/70140732我認為這是具有多個存儲庫的解決方案的示例。

我找到了一個解決方案,我可以像sequelize一樣使用存儲庫和事務,它使用我們啟動事務時提供的管理器,管理器中有一個方法withRepository object,它可以用來使用特定的查詢存儲庫。 所以我所做的是創建一個 BaseService,每次我必須查詢數據庫時,我將 function 作為最后一個參數傳遞給管理器,這也是可選的。 我在那里使用經理並執行以下操作。

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

就是這樣,如果你想要一個例子讓我知道我會實現它並在 github 存儲庫中共享。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM