0
0

More than 1 year has passed since last update.

TypeORMでロールバックの実装

Posted at

初めに

TypeORMを使用してDB操作を実装しているときに、「あっ、エラーが発生した時のロールバック処理も実装しないと」と思い、実装したプログラムを紹介します。

環境

  • Windows10
  • typeorm 0.2.34
  • typescript 4.3.2
  • node 14.17.0
  • Azure Database for MySQL サーバー

コード

Entityファイル

entity/CrawlerHistory.ts
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity("crawler_history")
export class CrawlerHistory {
  @PrimaryGeneratedColumn()
  readonly id?: number

  @Column("varchar", { name: "status", length: 30 })
  status!: string

  @Column("text", { name: "message" })
  message!: string

  @Column("datetime", { name: "create_date" })
  createDate!: string
}

メインファイル

1ファイルで紹介したかったため1ファイルにすべて詰め込んでありますが、
適宜管理しやすいようにファイルを分けたほうがいいと思います。

index.ts
import { createConnection, EntityManager, getManager } from "typeorm";
import fs from 'fs'
import { CrawlerHistory } from "./entity/CrawlerHistory";

//IIFE 即時関数
(async function main() {
  //db接続
  const connection = await createConnection({
    type: "mysql",//※1
    host: "{your host}",
    port: 3306,
    username: "{your user}",
    password: "{your password}",
    database: "{your database}",
    synchronize: false,
    ssl: { ca: fs.readFileSync('./ssl/DigiBalRoot.crt.pem') },//※2
    logging: false,
    entities: ["entity/**/*.js"],//※3
    migrations: ["migration/**/*.js"],
    subscribers: ["subscriber/**/*.js"],
    cli: {
      entitiesDir: 'entity',//※3
      migrationsDir: 'migration',
      subscribersDir: 'subscriber',
    }
  }).catch(err => { throw err; })

  if (connection) {//接続の確立
    console.log('connection open')
    await getManager().transaction(async (transactionalEntityManager) => {//※4
      await createCrawler_history({
        status: 'INFO',
        message: '登録しました',
        createDate: new Date().toISOString()
      }, transactionalEntityManager).then(() => console.log('登録'))
    }).catch(async () => {//※7
      console.log('ロールバックの実行')
    })
  } else {
    console.log('接続が失敗しました。')
  }
  await connection.close()//※5
  console.log('connection close')
})()


const createCrawler_history = async (body: CrawlerHistory, transactionalEntityManager: EntityManager) => {
  //DB接続
  await transactionalEntityManager.save(CrawlerHistory, body)
  throw new Error //※6
}

  • ※1
    今回使用するDBがmysqlのためmysqlとします。
    波括弧{}で囲われた部分は使用するDBの情報に置き換えてください。

  • ※2
    AzureDBの設定で接続のセキュリティ項目にて、SSL接続を強制にするを有効にしているとpemファイルが必要になります。
    保存したpemファイルのパスに置き換えてください。
    今回の例ではindex.ts直下にsslフォルダを作成しその中に保存しました。

  • ※3
    entityのファイルを作成した場所のパスです。

  • ※4
    トランザクション処理です。
    今回は1つしか実行していないが、この内部に書かれた関数内で例外が発生すると、実行していた SQL がロールバックされる。

  • ※5
    接続の切断メソッドです。

  • ※6
    今回の例ではこの場所でErrorを出している。
    正常に動かす場合はこの行をコメントアウトする。

  • ※7
    DBに関するものしかロールバックされないため、前に別の処理を行っていた場合はここでその処理についてロールバックする必要がある。
    例:私の場合はIBMCloudのDiscoveryに文書を登録し、
    そのあとに実行ログを残していたため、登録した文書を削除する処理を記述しました。

終わりに

TypeOrmはまだまだできることが多いので調べつつ、またいろいろ記事にしていけたらと思います!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0