概要
トランザクションの利用方法は2種類あります。
- クエリを実行する際に、明示的にTransactionオブジェクトを受け渡す
- ModelをTransactionオブジェクトに束縛する
明示的にTransactionオブジェクトを受け渡す
const { transaction } = require('objection');
await transaction(Project.knex(), async trx => {
const project = await Project
.query(trx)
.insert({ name: 'hoge' });
await project
.$relatedQuery('members', trx)
.insert({ name: 'hogepiyo', email: 'hogepiyo@example.com' });
});
transaction関数を実行することで、トランザクションを開始します。
第1引数にはknexインスタンス、第2引数にはコールバック関数を渡します。
knexインスタンスは、任意のModelのknexメソッド等で取得できます。
第2引数のコールバック関数は、引数としてTransactionオブジェクトを受け取ります。
このTransactionオブジェクトを、query
, $query
, または$relatedQuery
メソッドの最後の引数として渡すことで、クエリがトランザクション内で実行されます。
コールバック関数が返却したPromiseがresolveされると、トランザクションはコミットされます。
コールバック関数で返却されたPromiseがrejectされた場合、またはコールバック内で例外が発生した場合は、トランザクションはロールバックされます。
ModelをTransactionオブジェクトに束縛する
const { transaction } = require('objection');
await transaction(Project, Task, async (Project, Task) => {
// 引数のProject, Taskを介して発行されるクエリは、自動的にトランザクション内で実行される
const project = await Project
.query()
.insert({ name: 'hoge' });
const task = await Task
.query()
.insert({ name: 'sample', projectId: project.id });
// Transactionが束縛されたModelのインスタンスを使用してクエリを発行する際も、
// 同一トランザクション内で実行される
const users = await project
.$relatedQuery('members')
.insert({ name: 'hogepiyo', email: 'hogepiyo@example.com' });
// 引数のProject, Task以外のModelからクエリを発行すると、そのクエリはトランザクション内で処理されないので注意
// User
// .query()
// .insert({ name: 'fuga', email: 'fuga@example.com' });
});
transaction関数に、トランザクションを束縛したいModelを渡します。
最後の引数のコールバック関数には、Modelのコピーが渡されます。
Modelのコピーを介してクエリーを発行すると、各クエリが同一トランザクション内で実行されます。
Modelのコピー以外からクエリーを発行すると、同一トランザクション内では実行されないので注意が必要です。
参考元