はじめに
SalesforceではSOQLを使ってデータを取得できる便利な特性がある反面、SOQLクエリには1つのトランザクションでの使用回数のガバナ制限があり大規模な組織では工夫をしないと引っかかってしまうことも多々あります。
Apexでは、参照関係を持つオブジェクトを扱う際に、特定の親オブジェクトを子オブジェクトのリストから取得するためにSOQLを用います。Apexを始めたばかりの方は、次のようにfor文の中でSOQLを繰り返し実行することが多いです。
今回は、Apex初心者の方のためにListだけに頼らない、SetとMapを使ったオブジェクト取得のベストプラクティスを紹介することを目的としています。
for (Child child : childList) {
Parent parent = [SELECT Id, Name FROM Parent WHERE Id = :child.parentRef];
}
この方法は、処理件数が少ない場合には特に問題はありませんが、件数が多くなるとガバナ制限(SOQLクエリ制限)に引っかかりやすくなり、パフォーマンスも低下してしまいます。
SOQLをfor文の前で実行し、Mapを活用するベストプラクティス
ガバナ制限に引っかからず、効率的にデータを取得するために、for文の前にSOQLを一度だけ実行し、結果をMapに格納することでfor文の中で繰り返し検索することができます。これにより、SOQLの実行回数を最小限に抑えることが可能です。
以下がMapを使用したベストプラクティスの例です。
Set<Id> parentIdSet = new Set<Id>();
for (Child child : childList) {
parentIdSet.add(child.parentRef);
}
Map<Id, Parent> parentMap = new Map<Id, Parent>(
[SELECT Id, Name FROM Parent WHERE Id IN :parentIdSet]
);
for (Child child : childList) {
Parent parent = parentMap.get(child.parentRef);
// 必要な処理をここに記述
}
この方法では、まず parentIdSet に子オブジェクトの参照先IDをすべて追加し、次にそのIDリストを用いてSOQLを一度だけ実行します。取得した親オブジェクトは Map に格納されるため、for文の中で Map.get() メソッドを使って各親オブジェクトを効率よく取得できます。
まとめ
リストを操作する際には、SOQLクエリをfor文内で繰り返さないようにすることが重要です。Mapを活用して一度のクエリでデータを取得することで、ガバナ制限を意識しつつ、パフォーマンスの良いコードを書くことが可能です。ぜひ、この方法を参考にしてApexのコーディングスキルを向上させてください!