web-dev-qa-db-ja.com

nestjs / TypeOrmデータベーストランザクション

AとBの2つのサービスがあると仮定します。サービスAには次の機能があります。

  1. データを検証する
  2. データベースに変更を加えるサービスB関数を呼び出す
  3. さらにいくつかのことを行う
  4. データベースに変更を加える

ここで、次のステップ3または4のいずれかが失敗したと仮定します。サービスBがデータベースに変更を加えたため、それらの変更はまだ残っています。

この場合、データベースをロールバックする方法はありますか?私はデータベーストランザクションについて考えましたが、ネストjsでそれを行う方法を見つけることができませんでした。TypeOrmでサポートされていますが、ネストするのは自然ではありません。そうでない場合、サービスBによって行われた変更で「行き詰まっている」のですが、変更がなければAによって行われるはずでした。

どうもありがとう。

5
superuser123

多くのソリューションが利用可能ですが、それらはすべてSQLトランザクション管理に基づいている必要があります。

個人的には、データベースでコードを実行するときに同じEntityManagerインスタンスを使用するのが最も簡単な方法だと思います。次に、次のようなものを使用できます。

getConnection().transaction(entityManager -> {
    service1.doStuff1(entityManager);
    service2.doStuff2(entityManager);
});

ORM操作の外部で生のSQLを実行する場合に備えて、同じトランザクションにラップされるQueryRunnerインスタンスからEntityManagerを生成できます。また、RepositoryからEntityManagerインスタンスを生成する必要もあります。そうしないと、メイントランザクションの外部でコードが実行されます。

2
zenbeni

悲観的ロックを使用する必要があったので、ここでそれを解決しました。

NestJSにTypeormのインスタンスを挿入するようにConnectionを要求するだけでよいので、これは「ネスト」的な方法だと思います。

@Injectable()
class MyService {
  // 1. Inject the Typeorm Connection
  constructor(@InjectConnection() private connection: Connection) { }

  async findById(id: number): Promise<Thing> {
    return new Promise(resolve => {
      // 2. Do your business logic
      this.connection.transaction(async entityManager => {
        resolve(
          await entityManager.findOne(Thing, id, {
            lock: { mode: 'pessimistic_write' },
          }),
        );
      });
    });
  }
}

必要な他のロジックを.transactionブロック内に配置するだけで問題ありません。

注:.transactionメソッドによって提供されるentityManagerを使用する必要があります。そうしないと機能しません。

1
nathanl93

この場合、両方のデータベース操作に同じトランザクションマネージャを使用する必要があります。残念ながら、サンプルリポジトリはありませんが、ノードで継続ローカルストレージ(CLS)を使用する潜在的なソリューションを見つけました。

https://github.com/typeorm/typeorm/issues/1895

これはExpress.jsにも当てはまりますが、TransactionManagerのインスタンスを(たとえば、ネストミドルウェアに)作成して、リクエストコンテキストごとに保存できます。その後、上記のリンクで@Transactionデコレーター実装のアノテーションが付けられている場合、サービスメソッド呼び出し全体でこのトランザクションマネージャーを再利用できます。

関数チェーンにエラーがない場合、トランザクションマネージャは行われたすべての変更をコミットします。それ以外の場合、マネージャーは変更をロールバックします。

お役に立てれば!

0
ovidiup