この記事では、Apexの一括処理バッチについて取りあげます。
実際にApexバッチを使ってみて、以下のような疑問が解決したのでまとめてみました。
- 一括処理バッチが有効な場面は?
- 一括処理バッチの書き方は?
- Apexテストでの注意点は?
一括処理バッチの特徴
一括処理バッチの特徴として、以下が挙げられます。
- 大量データを扱ってもガバナ制限を超過しにくい
- 非同期処理として実行できる
まず、一括処理バッチは大量のデータを処理する際に有効です。
例えば、SOQL クエリによって取得されるレコードの合計数は50000件が上限ですが、一括処理バッチでは最大5000万件まで一度に取得することができます。
さらに、取得したレコードに対して一定数ごとにレコードを分割して処理を実行します。各処理は別トランザクションとなるため、ガバナ制限のカウントは毎回リセットされます。
したがって、一括処理バッチを用いることで大量データをガバナ制限を超過しないように処理することができるようになります。
また、一括処理バッチ使用すると非同期処理になります。したがって処理に時間がかかったとしても、ユーザはその間別の画面操作をすることができます。
以上の特徴から、大量データや、時間のかかる処理に対して力を発揮する機能だと言えます。
一括処理バッチの書き方
一括処理バッチは、Database.Batchable というインターフェースを使用します。Database.Batchable は、start(), execute(), finish() という3つのメソッドを持っています。
start() では、処理したいデータをクエリして返すようにします。返り値は Database.QueryLocator または Iterable(普通のリストの形など)のどちらかを返します。Database.QueryLocator を返すようにすると、最大5000万件まで取得することができます。
しかし、Database.QueryLocator を返す場合は、集計関数(GROUP BYなど)を使うことができません。集計関数を使いたい時はIterable を返すようにします。Iterable では通常のガバナ制限がそのまま適用されますが、このように柔軟に対応することができます。
execute() では、start() でクエリしてきたデータに対しての処理を記述します。execute() の処理はクエリしたデータを数件ごとに分割して実行されます。
finish() では、全てのデータに対して処理が終わったあと実行される処理を記述します。ユーザに対してバッチ実行が終了したことを通知する、などの処理が一般的です。
public class SampleBatch implements Database.Batchable<sObject> {
/* Database.QueryLocator を使う場合 */
public Database.QueryLocator start(Database.BatchableContext bc) {
// レコードをクエリ
return Database.getQueryLocator(
'SELECT ID FROM Account'
);
}
public void execute(Database.BatchableContext bc, List<P> records){
// レコードに対する処理を記述
}
public void finish(Database.BatchableContext bc){
// バッチ終了時の処理を記述
}
}
/* Iterable<sObject> を使う場合 */
public Iterable<sObject> start(Database.BatchableContext bc) {
List<Account> accList = [SELECT ID FROM Account];
return accList;
}
バッチの実行方法
バッチは以下のようにインスタンスを作成してから、Database.executeBatch() を呼び出すことで実行します。
SampleBatch batch = new SampleBatch();
Database.executeBatch(batch);
以下のようにバッチサイズを指定して実行することもできます。
SampleBatch batch = new SampleBatch();
Database.executeBatch(batch, 100); // 100件ごとに実行
Apexテストでの注意点
Apexテストでバッチのテストをする際は、1回のバッチ実行分の処理しかテストできません。例えば、1000件クエリして200レコード単位で5回分の処理をテスト、みたいなことはできません。
また、Apexテストを記述する際はTest.startTest() と Test.stopTest() を使う必要があります。詳しくは以下の記事を参照して下さい。
Apexテストで Test.startTest(), Test.stopTest()を使う意味
まとめ
- 大量データや、時間のかかる処理に対して有効
- Database.Batchableというインターフェースを使用する
- Database.QueryLocator を使う場合は集計関数を使えないことに注意
- Apexテストでは、1回のバッチ実行分しかテストできないことに注意
コメント