エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

【意訳+要約】NestJSとTypeORMによる高度なトランザクション管理

※本記事は、Bardによる意訳+翻訳を活用し、レイアウト調整したものです。
※感想は、オリジナルです。

原文

Advanced Transaction Management with NestJS & TypeORM | by Muhammet Özen | Medium

意訳+要約

NestJSでトランザクション管理を理解する

NestJSは、Node.jsで構築されたフルスタックフレームワークです。TypeORMは、NestJSでよく使用されるORM(オブジェクトリレーショナルマッピング)ライブラリです。トランザクション管理は、複数のSQLステートメントを単一のユニットとして実行し、エラーが発生した場合にすべてをロールバックするプロセスです。

本記事では、NestJSとTypeORMを使用してトランザクション管理を理解するための基礎を解説します。

トランザクションの基本

トランザクションは、データベースの整合性を維持するために重要です。トランザクションが正常に完了した場合、すべてのSQLステートメントが実行されます。エラーが発生した場合、すべてのステートメントロールバックされます。

トランザクションは、次の2つの部分で構成されます。

NestJSとTypeORMでのトランザクション管理

NestJSとTypeORMでは、トランザクションを管理するためのさまざまな方法を提供しています。

トランザクションスコープ

最も簡単な方法は、トランザクションスコープを使用することです。トランザクションスコープは、@Transaction()デコレータを使用して定義します。

@Transaction()
async createUser(user: UserDto) {
  await this.userRepository.save(user);
  await this.addressRepository.save(user.address);
}

コードは慎重に使用してください。詳細

このコードは、createUser()メソッドをトランザクションスコープで定義しています。このメソッドが正常に完了した場合、両方のリポジトリへの保存がコミットされます。エラーが発生した場合、両方の保存がロールバックされます。

トランザクションマネージャー

トランザクションスコープを使用すると、メソッドのスコープ内でのみトランザクションが有効になります。トランザクションをアプリケーション全体で有効にするには、トランザクションマネージャーを使用します。

トランザクションマネージャーは、@Module()デコレータを使用して定義します。

@Module({
  imports: [
    TypeORMModule.forRoot({
      // ...
    }),
    TransactionManagerModule.forRoot({
      // ...
    }),
  ],
  providers: [
    // ...
    TransactionManager,
  ],
})
export class AppModule {}

コードは慎重に使用してください。詳細

トランザクションマネージャーを有効にするには、@UseTransaction()デコレータを使用してコントローラーまたはサービスに適用します。

@Controller()
@UseTransaction()
export class UserController {
  constructor(private readonly userRepository: UserRepository) {}

  async createUser(user: UserDto) {
    await this.userRepository.save(user);
    await this.addressRepository.save(user.address);
  }
}

コードは慎重に使用してください。詳細

このコードは、UserControllerコントローラーをトランザクションマネージャーで有効にしています。このコントローラー内のすべてのメソッドは、トランザクションスコープで実行されます。

トランザクションエクスプローラ

トランザクションをさらに細かく制御するには、トランザクションエクスプローラーを使用します。トランザクションエクスプローラーは、@UseTransactional()デコレータを使用してコントローラーまたはサービスに適用します。

@Controller()
@UseTransactional()
export class UserController {
  constructor(private readonly userRepository: UserRepository) {}

  async createUser(user: UserDto) {
    await this.userRepository.beginTransaction();
    try {
      await this.userRepository.save(user);
      await this.addressRepository.save(user.address);
      await this.userRepository.commitTransaction();
    } catch (error) {
      await this.userRepository.rollbackTransaction();
      throw error;
    }
  }
}

コードは慎重に使用してください。詳細

このコードは、UserControllerコントローラーをトランザクションエクスプローラーで有効にしています。このコントローラー内のすべてのメソッドは、トランザクションスコープで実行されます。また、メソッド内でトランザクションを開始、コミット、またはロールバックできます。

Bardさんに聞いてみた

Q:TypeORMは、Springに近い記述方法でトランザクション管理を行うのでしょうか?

基本的には近いです。

TypeORMでは、トランザクションを管理するための3つの方法を提供しています。

このうち、トランザクションスコープは、Springの@Transactionalアノテーションに相当します。トランザクションスコープを使用すると、メソッドのスコープ内でのみトランザクションが有効になります。

トランザクションマネージャーは、Springの@EnableTransactionManagementアノテーションに相当します。トランザクションマネージャーを使用すると、アプリケーション全体でトランザクションが有効になります。

トランザクションエクスプローラーは、Springの@Transactionalアノテーションと@EnableTransactionManagementアノテーションを組み合わせた機能です。トランザクションエクスプローラーを使用すると、トランザクションをさらに細かく制御できます。

Q:TypeORMは、Springの影響を受けているのでしょうか?

はい、TypeORMはSpringの影響を受けています。

TypeORMのトランザクション管理は、Springのトランザクション管理と基本的な概念は同じです。トランザクションスコープ、トランザクションマネージャー、トランザクションエクスプローラーの3つの方法を提供しており、Springの@Transactionalアノテーション@EnableTransactionManagementアノテーション@Transactionalデコレータと似ています。

また、TypeORMの開発者は、Springの開発者であるRod Johnson氏と協力しています。Rod Johnson氏は、TypeORMのトランザクション管理の設計にも関わっています。

このように、TypeORMはSpringの影響を強く受けており、Springの開発者との協力によって開発されています。

なお、TypeORMはSpringの影響を受けている一方で、独自の機能も備えています。たとえば、TypeORMは、トランザクションの分離レベルを指定できる機能や、トランザクションロールバック時に、コミット済みのステートメントロールバックできる機能を備えています。

感想+雑記

Springを使っている身からすると、コードはだいぶ分かりやすかった。
TypeScriptは、個人開発のフロントエンドで使っているが、バックエンドでもイケそうだなって感じてきた。
まぁ、バックエンドの処理をどこで書くのかだろうな。。。
Next.jsやElectronなら、フロントエンドだとしても使いそう。

型づけが強力だから、利用想定は、RDBだろうな。
NoSQLでの利用想定はあるのだろうか?
最近、TypeORMを知ったので、興味を持って要約を見ることができた。
ORマッパーとしてではなく、トランザクション管理もできるんだな。