TypeORM のトランザクション処理を利用する
TypeScript ベースの O/R マッパー、TypeORM で実現できる、トランザクション処理を試してみる。
前提とする環境は、前回の記事で紹介した TypeORM + PostgreSQL 環境。
import { createConnection, getManager, getRepository } from 'typeorm';
import dbConfig from './db-config';
import Customer from './entities/customer';
try {
// DB に接続する
const connection = await createConnection(dbConfig);
// トランザクションを開始する
await getManager().transaction(async (transactionalEntityManager) => {
// この async 関数内で例外が発生すると、実行していた SQL がロールバックされる
// 思い思いに複数の SQL を実行してみたり…
const newCustomer = new Customer('Neo');
const savedCustomer = await transactionalEntityManager.save(newCustomer);
const anotherCustomer = new Customer('Another');
const insertedCustomer = await transactionalEntityManager.save(Customer, anotherCustomer);
// 最後まで正常に終了すればコミットされる
});
}
catch(error) {
console.error('Failed To Exec Transaction : ', error);
}
こんな感じ。
getManager().transaction()
内の async
関数内がトランザクションになる。
この中で何らかの例外が発生すると、途中まで実行していた save()
や insert()
等の SQL はロールバックされる。
SQL 実行に限らず、どんな例外であってもロールバックできるので、例えば複数のテーブルの更新が成功しないとダメな場合だとか、DB 更新と同時にファイルを書き出したいとかいう場合にも使える。
当然ながら、TypeORM が自動的にロールバックしてくれるのは SQL のみなので、DB 操作以外のロールバック処理は自前で catch
句内で行う必要がある。
EntityRepository ではなく TransactionalEntityManager を利用して SQL 実行するところが若干違うので、実装時はちょっとトライアル & エラーが必要かも〜。