Node.jsの代表的なO/RMであるSequelizeの第三弾。
第1回ではインストールから基本的な利用方法、第2回ではSELECT文の使い方を取り上げました。今回はINSERTやUPDATEなど更新系の処理に欠かせない「トランザクション」です。
目次
インストール
事前準備や基本的な利用方法については第1回を参照ください。
準備
今回はMakerモデルを作成しMySQLへ反映しておきます。SQL実行時にかんたんにエラーを発生させるためnameにunique制約を付けました。
const Maker = sequelize.define('Maker', {
name: { type: DataTypes.STRING(128), unique: true },
CountryId: { type: DataTypes.STRING(2) }
},{timestamps: false})
await Maker.sync();
2種類のトランザクション
Sequelizeには次の2種類のトランザクションが用意されています。どちらが良いという話でも無いと思いますのでお好みでどうぞ。
- UnManaged Transactions
- 手動モード。自分でコミットやロールバックを書く必要があります。
- Managed Transactions
- 自動モード。正常に処理が終了すると自動的にコミットされ、エラーが発生すると自動的にロールバックします。
UnManaged Transactions
まずは手動モードから。こちらが他のフレームワークなどでも見かけるので個人的には馴染み深いですね。
// トランザクションを作成
const t = await sequelize.transaction();
try {
// 同じデータを2回挿入
// nameにはunique制約があるので2回目でエラーになる
await Maker.create({name: 'Honda', CountryId: 'JP'}, {transaction: t})
await Maker.create({name: 'Honda', CountryId: 'JP'}, {transaction: t})
await t.commit() // コミット
}
catch(error) {
await t.rollback() // ロールバック
}
// MySQLから切断
await sequelize.close()
Managed Transactions
こちらが自動モード。どこにもcommitやrollbackの文字が出てきませんが裏側ではしっかり行われています。
try {
await sequelize.transaction(async (t) => {
// 同じデータを2回挿入
// nameにはunique制約があるので2回目でエラーになる
await Maker.create({name: 'Honda', CountryId: 'JP'}, {transaction: t})
await Maker.create({name: 'Honda', CountryId: 'JP'}, {transaction: t})
})
}
catch (error) {
console.error(error)
}
トランザクション分離レベル
MySQL(InnoDB)のデフォルト値は「REPEATABLE READ」ですが、SQL実行時にSequelizeでも変更することが可能です。次の定数が用意されていますので、これをインスタンスを生成時か実行時のどちらかでセットします。
const { Transaction } = require('sequelize');
Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED
Transaction.ISOLATION_LEVELS.READ_COMMITTED
Transaction.ISOLATION_LEVELS.REPEATABLE_READ
Transaction.ISOLATION_LEVELS.SERIALIZABLE
インスタンス生成時に指定
すべてのトランザクションで変更したい場合はこちらを利用します。まぁ全部変えるならDBの設定変えた方が早い気もしますが何らかの事情で出来ない場合にどうぞ。
const { Sequelize, Transaction } = require('sequelize')
const sequelize = new Sequelize('database_development', 'root', null, {
host: 'localhost',
dialect: 'mysql',
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
})
実行時に指定
手動モードも自動モードもどちらもsequelize.transaction()
の引数として渡してやります。
const { Transaction } = require('sequelize')
// 手動モード
const t = await sequelize.transaction({
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
})
const { Transaction } = require('sequelize')
// 自動モード
await sequelize.transaction({
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
},
async (t) => {
// 実際の処理
await Maker.create({name: 'Honda', CountryId: 'JP'}, {transaction: t})
}
);
続き
参考ページ
このブログを応援する
お寄せいただいたお気持ちは全額サーバ代や次の記事を執筆するための原資として活用させていただいております。この記事が参考になった場合などぜひご検討ください。
同じカテゴリの記事
- [Node.js] SequelizeでMySQLを利用する – その5「ToDoアプリ作成編」
- [Node.js] SequelizeでMySQLを利用する – その4「マイグレーション編」
- [Node.js] SequelizeでMySQLを利用する – その2「SELECT文編」
- [Node.js] SequelizeでMySQLを利用する – その1「チュートリアル編」
- [JavaScript] クレジットカード番号から国際ブランドを特定する
- [JavaScript] クレジットカード番号が正しいか検証する
- [Node.js] ClamAVでウイルスチェック
- [Node.js] 指定した時間sleepする – Promise版